From f1f2b51cd69212e2a695938ef9d53f6825b60604 Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 16:31:10 -0700 Subject: [PATCH 001/120] start v9 branch, pin API level to major version --- Dalamud/Dalamud.csproj | 2 +- Dalamud/Plugin/Internal/PluginManager.cs | 3 ++- README.md | 23 +++++++++++------------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 116ebd008..6e6a01fa9 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 7.6.0.0 + 9.0.0.0 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 9df249dd7..0ff63f2c0 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -49,8 +49,9 @@ internal partial class PluginManager : IDisposable, IServiceType { /// /// The current Dalamud API level, used to handle breaking changes. Only plugins with this level will be loaded. + /// As of Dalamud 9.x, this always matches the major version number of Dalamud. /// - public const int DalamudApiLevel = 8; + public static int DalamudApiLevel => Assembly.GetExecutingAssembly().GetName().Version!.Major; /// /// Default time to wait between plugin unload and plugin assembly unload. diff --git a/README.md b/README.md index f98961c3e..97dd4e9dd 100644 --- a/README.md +++ b/README.md @@ -26,23 +26,22 @@ Thanks to Mino, whose work has made this possible! These components are used in order to load Dalamud into a target process. Dalamud can be loaded via DLL injection, or by rewriting a process' entrypoint. -| Name | Purpose | -|---|---| -| *Dalamud.Injector.Boot* (C++) | Loads the .NET Core runtime into a process via hostfxr and kicks off Dalamud.Injector | -| *Dalamud.Injector* (C#) | Performs DLL injection on the target process | -| *Dalamud.Boot* (C++) | Loads the .NET Core runtime into the active process and kicks off Dalamud, or rewrites a target process' entrypoint to do so | -| *Dalamud* (C#) | Core API, game bindings, plugin framework | -| *Dalamud.CorePlugin* (C#) | Testbed plugin that can access Dalamud internals, to prototype new Dalamud features | +| Name | Purpose | +|-------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| *Dalamud.Injector.Boot* (C++) | Loads the .NET Core runtime into a process via hostfxr and kicks off Dalamud.Injector | +| *Dalamud.Injector* (C#) | Performs DLL injection on the target process | +| *Dalamud.Boot* (C++) | Loads the .NET Core runtime into the active process and kicks off Dalamud, or rewrites a target process' entrypoint to do so | +| *Dalamud* (C#) | Core API, game bindings, plugin framework | +| *Dalamud.CorePlugin* (C#) | Testbed plugin that can access Dalamud internals, to prototype new Dalamud features | ## Branches We are currently working from the following branches. -| Name | Purpose | .NET Version | Track | -|---|---|---|---| -| *master* | Current release branch | .NET 6.0.3 (March 2022) | Release & Staging | -| *net7* | Upgrade to .NET 7 | .NET 7.0.0 (November 2022) | net7 | -| *api3* | Legacy version, no longer in active use | .NET Framework 4.7.2 (April 2017) | - | +| Name | API Level | Purpose | .NET Version | Track | +|----------|-----------|------------------------------------------------------------|----------------------------|-------------------| +| *master* | **8** | Current release branch | .NET 7.0.0 (November 2022) | Release & Staging | +| *v9* | **9** | Next major version, slated for release alongside Patch 6.5 | .NET 7.0.0 (November 2022) | v9 |
From f61e6335174b7ee2356c8ee1a7ae4acbabfdda96 Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 17:11:20 -0700 Subject: [PATCH 002/120] cleanup: remove obsolete FrameworkAddressResolver.BaseAddress property --- Dalamud/Game/FrameworkAddressResolver.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Dalamud/Game/FrameworkAddressResolver.cs b/Dalamud/Game/FrameworkAddressResolver.cs index e3d128f0f..36915d7a9 100644 --- a/Dalamud/Game/FrameworkAddressResolver.cs +++ b/Dalamud/Game/FrameworkAddressResolver.cs @@ -5,14 +5,8 @@ namespace Dalamud.Game; /// /// The address resolver for the class. /// -public sealed unsafe class FrameworkAddressResolver : BaseAddressResolver +public sealed class FrameworkAddressResolver : BaseAddressResolver { - /// - /// Gets the base address of the Framework object. - /// - [Obsolete("Please use FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance() instead.")] - public IntPtr BaseAddress => new(FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance()); - /// /// Gets the address for the function that is called once the Framework is destroyed. /// From ddf4e56ee666217a5b2c7b8828c5e6cab719b4ae Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 17:15:22 -0700 Subject: [PATCH 003/120] cleanup: remove obsolete SeStringManager class --- .../Text/SeStringHandling/SeStringManager.cs | 111 ------------------ Dalamud/Memory/MemoryHelper.cs | 20 ++-- 2 files changed, 10 insertions(+), 121 deletions(-) delete mode 100644 Dalamud/Game/Text/SeStringHandling/SeStringManager.cs diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs b/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs deleted file mode 100644 index f0b38d429..000000000 --- a/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections.Generic; - -using Dalamud.IoC; -using Dalamud.IoC.Internal; -using Lumina.Excel.GeneratedSheets; - -namespace Dalamud.Game.Text.SeStringHandling; - -/// -/// This class facilitates creating new SeStrings and breaking down existing ones into their individual payload components. -/// -[PluginInterface] -[InterfaceVersion("1.0")] -[ServiceManager.BlockingEarlyLoadedService] -[Obsolete("This class is obsolete. Please use the static methods on SeString instead.")] -public sealed class SeStringManager : IServiceType -{ - [ServiceManager.ServiceConstructor] - private SeStringManager() - { - } - - /// - /// Parse a binary game message into an SeString. - /// - /// Pointer to the string's data in memory. - /// Length of the string's data in memory. - /// An SeString containing parsed Payload objects for each payload in the data. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public unsafe SeString Parse(byte* ptr, int len) => SeString.Parse(ptr, len); - - /// - /// Parse a binary game message into an SeString. - /// - /// Binary message payload data in SE's internal format. - /// An SeString containing parsed Payload objects for each payload in the data. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public unsafe SeString Parse(ReadOnlySpan data) => SeString.Parse(data); - - /// - /// Parse a binary game message into an SeString. - /// - /// Binary message payload data in SE's internal format. - /// An SeString containing parsed Payload objects for each payload in the data. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public SeString Parse(byte[] bytes) => SeString.Parse(new ReadOnlySpan(bytes)); - - /// - /// Creates an SeString representing an entire Payload chain that can be used to link an item in the chat log. - /// - /// The id of the item to link. - /// Whether to link the high-quality variant of the item. - /// An optional name override to display, instead of the actual item name. - /// An SeString containing all the payloads necessary to display an item link in the chat log. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public SeString CreateItemLink(uint itemId, bool isHQ, string displayNameOverride = null) => SeString.CreateItemLink(itemId, isHQ, displayNameOverride); - - /// - /// Creates an SeString representing an entire Payload chain that can be used to link an item in the chat log. - /// - /// The Lumina Item to link. - /// Whether to link the high-quality variant of the item. - /// An optional name override to display, instead of the actual item name. - /// An SeString containing all the payloads necessary to display an item link in the chat log. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public SeString CreateItemLink(Item item, bool isHQ, string displayNameOverride = null) => SeString.CreateItemLink(item, isHQ, displayNameOverride); - - /// - /// Creates an SeString representing an entire Payload chain that can be used to link a map position in the chat log. - /// - /// The id of the TerritoryType for this map link. - /// The id of the Map for this map link. - /// The raw x-coordinate for this link. - /// The raw y-coordinate for this link.. - /// An SeString containing all of the payloads necessary to display a map link in the chat log. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public SeString CreateMapLink(uint territoryId, uint mapId, int rawX, int rawY) => - SeString.CreateMapLink(territoryId, mapId, rawX, rawY); - - /// - /// Creates an SeString representing an entire Payload chain that can be used to link a map position in the chat log. - /// - /// The id of the TerritoryType for this map link. - /// The id of the Map for this map link. - /// The human-readable x-coordinate for this link. - /// The human-readable y-coordinate for this link. - /// An optional offset to account for rounding and truncation errors; it is best to leave this untouched in most cases. - /// An SeString containing all of the payloads necessary to display a map link in the chat log. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public SeString CreateMapLink(uint territoryId, uint mapId, float xCoord, float yCoord, float fudgeFactor = 0.05f) => SeString.CreateMapLink(territoryId, mapId, xCoord, yCoord, fudgeFactor); - - /// - /// Creates an SeString representing an entire Payload chain that can be used to link a map position in the chat log, matching a specified zone name. - /// - /// The name of the location for this link. This should be exactly the name as seen in a displayed map link in-game for the same zone. - /// The human-readable x-coordinate for this link. - /// The human-readable y-coordinate for this link. - /// An optional offset to account for rounding and truncation errors; it is best to leave this untouched in most cases. - /// An SeString containing all of the payloads necessary to display a map link in the chat log. - [Obsolete("This method is obsolete. Please use the static methods on SeString instead.", true)] - public SeString CreateMapLink(string placeName, float xCoord, float yCoord, float fudgeFactor = 0.05f) => SeString.CreateMapLink(placeName, xCoord, yCoord, fudgeFactor); - - /// - /// Creates a list of Payloads necessary to display the arrow link marker icon in chat - /// with the appropriate glow and coloring. - /// - /// A list of all the payloads required to insert the link marker. - [Obsolete("This data is obsolete. Please use the static version on SeString instead.", true)] - public List TextArrowPayloads() => new(SeString.TextArrowPayloads); -} diff --git a/Dalamud/Memory/MemoryHelper.cs b/Dalamud/Memory/MemoryHelper.cs index 5b640f64c..3ceecf6a6 100644 --- a/Dalamud/Memory/MemoryHelper.cs +++ b/Dalamud/Memory/MemoryHelper.cs @@ -167,7 +167,7 @@ public static unsafe class MemoryHelper /// Read a UTF-8 encoded string from a specified memory address. ///
/// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The read in string. @@ -178,7 +178,7 @@ public static unsafe class MemoryHelper /// Read a string with the given encoding from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The encoding to use to decode the string. @@ -193,7 +193,7 @@ public static unsafe class MemoryHelper /// Read a UTF-8 encoded string from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The maximum length of the string. @@ -205,7 +205,7 @@ public static unsafe class MemoryHelper /// Read a string with the given encoding from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The encoding to use to decode the string. @@ -284,7 +284,7 @@ public static unsafe class MemoryHelper /// Read a UTF-8 encoded string from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The read in string. @@ -295,7 +295,7 @@ public static unsafe class MemoryHelper /// Read a string with the given encoding from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The encoding to use to decode the string. @@ -307,7 +307,7 @@ public static unsafe class MemoryHelper /// Read a UTF-8 encoded string from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The read in string. @@ -319,7 +319,7 @@ public static unsafe class MemoryHelper /// Read a string with the given encoding from a specified memory address. /// /// - /// Attention! If this is an SeString, use the to decode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to read from. /// The encoding to use to decode the string. @@ -426,7 +426,7 @@ public static unsafe class MemoryHelper /// Write a UTF-8 encoded string to a specified memory address. /// /// - /// Attention! If this is an SeString, use the to encode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to write to. /// The string to write. @@ -437,7 +437,7 @@ public static unsafe class MemoryHelper /// Write a string with the given encoding to a specified memory address. /// /// - /// Attention! If this is an SeString, use the to encode or the applicable helper method. + /// Attention! If this is an , use the applicable helper methods to decode. /// /// The memory address to write to. /// The string to write. From 276ad3733f67cc4f886c8f78b3bb3d3207a4d391 Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 17:19:14 -0700 Subject: [PATCH 004/120] cleanup: remove obsolete Hook ctors --- Dalamud/Hooking/Hook.cs | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs index 74b9e6384..558b6bde1 100644 --- a/Dalamud/Hooking/Hook.cs +++ b/Dalamud/Hooking/Hook.cs @@ -26,32 +26,6 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate private readonly Hook? compatHookImpl; - /// - /// Initializes a new instance of the class. - /// Hook is not activated until Enable() method is called. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - [Obsolete("Use Hook.FromAddress instead.")] - public Hook(IntPtr address, T detour) - : this(address, detour, false, Assembly.GetCallingAssembly()) - { - } - - /// - /// Initializes a new instance of the class. - /// Hook is not activated until Enable() method is called. - /// Please do not use MinHook unless you have thoroughly troubleshot why Reloaded does not work. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - /// Use the MinHook hooking library instead of Reloaded. - [Obsolete("Use Hook.FromAddress instead.")] - public Hook(IntPtr address, T detour, bool useMinHook) - : this(address, detour, useMinHook, Assembly.GetCallingAssembly()) - { - } - /// /// Initializes a new instance of the class. /// @@ -61,19 +35,6 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate this.address = address; } - [Obsolete("Use Hook.FromAddress instead.")] - private Hook(IntPtr address, T detour, bool useMinHook, Assembly callingAssembly) - { - if (EnvironmentConfiguration.DalamudForceMinHook) - useMinHook = true; - - this.address = address = HookManager.FollowJmp(address); - if (useMinHook) - this.compatHookImpl = new MinHookHook(address, detour, callingAssembly); - else - this.compatHookImpl = new ReloadedHook(address, detour, callingAssembly); - } - /// /// Gets a memory address of the target function. /// From efec6eada2557974433d6471a450391f4c522fb7 Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 17:21:15 -0700 Subject: [PATCH 005/120] cleanup: remove obsolete method to reload all plugins --- Dalamud/Plugin/Internal/PluginManager.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 0ff63f2c0..47f96dea4 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -580,23 +580,6 @@ internal partial class PluginManager : IDisposable, IServiceType tokenSource.Token); } - /// - /// Reload all loaded plugins. - /// - /// A task. - [Obsolete("This method should no longer be used and will be removed in a future release.")] - public Task ReloadAllPluginsAsync() - { - lock (this.pluginListLock) - { - return Task.WhenAll(this.InstalledPlugins - .Where(x => x.IsLoaded) - .ToList() - .Select(x => Task.Run(async () => await x.ReloadAsync())) - .ToList()); - } - } - /// /// Reload the PluginMaster for each repo, filter, and event that the list has updated. /// From 292e0c2df84a0cd1f6c2afe07b3a88853792d76f Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 17:25:05 -0700 Subject: [PATCH 006/120] cleanup: remove obsoleted properties in DalamudPluginInterface --- Dalamud/Plugin/DalamudPluginInterface.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 35b8bbbc7..76e5a65d5 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -205,18 +205,6 @@ public sealed class DalamudPluginInterface : IDisposable /// public XivChatType GeneralChatType { get; private set; } - /// - /// Gets a list of installed plugin names. - /// - [Obsolete($"This property is obsolete. Use {nameof(InstalledPlugins)} instead.")] - public List PluginNames => Service.Get().InstalledPlugins.Select(p => p.Manifest.Name).ToList(); - - /// - /// Gets a list of installed plugin internal names. - /// - [Obsolete($"This property is obsolete. Use {nameof(InstalledPlugins)} instead.")] - public List PluginInternalNames => Service.Get().InstalledPlugins.Select(p => p.Manifest.InternalName).ToList(); - /// /// Gets a list of installed plugins along with their current state. /// From 8bd0cb0c57e821e4cbb88612f5a74ad6731c9a39 Mon Sep 17 00:00:00 2001 From: Ava Chaney Date: Sat, 27 May 2023 17:37:41 -0700 Subject: [PATCH 007/120] cleanup: remove obsolete Util.HttpClient, Util.CopyTo() --- Dalamud/Utility/Util.cs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index ecf672caf..3d472a2c7 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -35,13 +35,6 @@ public static class Util private static ulong moduleStartAddr; private static ulong moduleEndAddr; - /// - /// Gets an httpclient for usage. - /// Do NOT await this. - /// - [Obsolete($"Use Service<{nameof(HappyHttpClient)}> instead.")] - public static HttpClient HttpClient { get; } = Service.Get().SharedHttpClient; - /// /// Gets the assembly version of Dalamud. /// @@ -493,21 +486,6 @@ public static class Util return Encoding.UTF8.GetString(mso.ToArray()); } - /// - /// Copy one stream to another. - /// - /// The source stream. - /// The destination stream. - /// The maximum length to copy. - [Obsolete("Use Stream.CopyTo() instead", true)] - public static void CopyTo(Stream src, Stream dest, int len = 4069) - { - var bytes = new byte[len]; - int cnt; - - while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) dest.Write(bytes, 0, cnt); - } - /// /// Heuristically determine if Dalamud is running on Linux/WINE. /// From 6bc7ebaff2d0d1d1cd2cd1486bc2bbf611066d73 Mon Sep 17 00:00:00 2001 From: kal <35899782+kalilistic@users.noreply.github.com> Date: Mon, 29 May 2023 15:59:44 -0400 Subject: [PATCH 008/120] feat: remove obsolete icons (#1147) --- .../Interface/FontAwesome/FontAwesomeIcon.cs | 3087 ----------------- 1 file changed, 3087 deletions(-) diff --git a/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs b/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs index 368ca55fe..3d21ea86c 100644 --- a/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs +++ b/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs @@ -19,28 +19,6 @@ public enum FontAwesomeIcon /// None = 0, - /// - /// The Font Awesome "500px" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "500px" })] - _500Px = 0xF26E, - - /// - /// The Font Awesome "accessible-icon" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "accessible icon", "accessibility", "handicap", "person", "wheelchair", "wheelchair-alt" })] - [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Medical + Health", "Transportation", "Users + People" })] - AccessibleIcon = 0xF368, - - /// - /// The Font Awesome "accusoft" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "accusoft" })] - Accusoft = 0xF369, - /// /// The Font Awesome "acquisitionsincorporated" icon unicode character. /// @@ -75,40 +53,12 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams", "Design", "Editing", "Photos + Images", "Shapes" })] Adjust = 0xF042, - /// - /// The Font Awesome "adn" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "adn" })] - Adn = 0xF170, - /// /// The Font Awesome "adobe" icon unicode character. /// [Obsolete] Adobe = 0xF778, - /// - /// The Font Awesome "adversal" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "adversal" })] - Adversal = 0xF36A, - - /// - /// The Font Awesome "affiliatetheme" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "affiliatetheme" })] - Affiliatetheme = 0xF36B, - - /// - /// The Font Awesome "airbnb" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "airbnb" })] - Airbnb = 0xF834, - /// /// The Font Awesome "spray-can-sparkles" icon unicode character. /// @@ -116,13 +66,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Automotive" })] AirFreshener = 0xF5D0, - /// - /// The Font Awesome "algolia" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "algolia" })] - Algolia = 0xF36C, - /// /// The Font Awesome "align-center" icon unicode character. /// @@ -151,14 +94,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] AlignRight = 0xF038, - /// - /// The Font Awesome "alipay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "alipay" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - Alipay = 0xF642, - /// /// The Font Awesome "hand-dots" icon unicode character. /// @@ -166,21 +101,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Hands", "Medical + Health" })] Allergies = 0xF461, - /// - /// The Font Awesome "amazon" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "amazon" })] - Amazon = 0xF270, - - /// - /// The Font Awesome "amazon-pay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "amazon pay" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - AmazonPay = 0xF42C, - /// /// The Font Awesome "truck-medical" icon unicode character. /// @@ -195,13 +115,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Communication" })] AmericanSignLanguageInterpreting = 0xF2A3, - /// - /// The Font Awesome "amilia" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "amilia" })] - Amilia = 0xF36D, - /// /// The Font Awesome "anchor" icon unicode character. /// @@ -237,20 +150,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Maritime" })] AnchorLock = 0xE4AD, - /// - /// The Font Awesome "android" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "android", "robot" })] - Android = 0xF17B, - - /// - /// The Font Awesome "angellist" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "angellist" })] - Angellist = 0xF209, - /// /// The Font Awesome "angles-down" icon unicode character. /// @@ -314,20 +213,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] Angry = 0xF556, - /// - /// The Font Awesome "angrycreative" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "angrycreative" })] - Angrycreative = 0xF36E, - - /// - /// The Font Awesome "angular" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "angular" })] - Angular = 0xF420, - /// /// The Font Awesome "ankh" icon unicode character. /// @@ -335,20 +220,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion" })] Ankh = 0xF644, - /// - /// The Font Awesome "apper" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "apper" })] - Apper = 0xF371, - - /// - /// The Font Awesome "apple" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "apple", "fruit", "ios", "mac", "operating system", "os", "osx" })] - Apple = 0xF179, - /// /// The Font Awesome "apple-whole" icon unicode character. /// @@ -356,28 +227,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Education", "Food + Beverage", "Fruits + Vegetables" })] AppleAlt = 0xF5D1, - /// - /// The Font Awesome "apple-pay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "apple pay" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - ApplePay = 0xF415, - - /// - /// The Font Awesome "app-store" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "app store" })] - AppStore = 0xF36F, - - /// - /// The Font Awesome "app-store-ios" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "app store ios" })] - AppStoreIos = 0xF370, - /// /// The Font Awesome "box-archive" icon unicode character. /// @@ -728,13 +577,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowUpRightFromSquare = 0xF08E, - /// - /// The Font Awesome "artstation" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "artstation" })] - Artstation = 0xF77A, - /// /// The Font Awesome "ear-listen" icon unicode character. /// @@ -750,13 +592,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Punctuation + Symbols", "Spinners" })] Asterisk = 0xF069, - /// - /// The Font Awesome "asymmetrik" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "asymmetrik" })] - Asymmetrik = 0xF372, - /// /// The Font Awesome "at" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x40. @@ -772,13 +607,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps", "Travel + Hotel" })] Atlas = 0xF558, - /// - /// The Font Awesome "atlassian" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "atlassian" })] - Atlassian = 0xF77B, - /// /// The Font Awesome "atom" icon unicode character. /// @@ -786,13 +614,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Education", "Energy", "Religion", "Science", "Science Fiction", "Spinners" })] Atom = 0xF5D2, - /// - /// The Font Awesome "audible" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "audible" })] - Audible = 0xF373, - /// /// The Font Awesome "audio-description" icon unicode character. /// @@ -807,27 +628,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] AustralSign = 0xE0A9, - /// - /// The Font Awesome "autoprefixer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "autoprefixer" })] - Autoprefixer = 0xF41C, - - /// - /// The Font Awesome "avianex" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "avianex" })] - Avianex = 0xF374, - - /// - /// The Font Awesome "aviato" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "aviato" })] - Aviato = 0xF421, - /// /// The Font Awesome "award" icon unicode character. /// @@ -835,13 +635,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Education", "Political" })] Award = 0xF559, - /// - /// The Font Awesome "aws" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "aws" })] - Aws = 0xF375, - /// /// The Font Awesome "baby" icon unicode character. /// @@ -940,13 +733,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Editing", "Medical + Health" })] BandAid = 0xF462, - /// - /// The Font Awesome "bandcamp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bandcamp" })] - Bandcamp = 0xF2D5, - /// /// The Font Awesome "bangladeshi-taka-sign" icon unicode character. /// @@ -1038,13 +824,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Energy" })] BatteryThreeQuarters = 0xF241, - /// - /// The Font Awesome "battle-net" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "battle net" })] - BattleNet = 0xF835, - /// /// The Font Awesome "bed" icon unicode character. /// @@ -1059,20 +838,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Maps" })] Beer = 0xF0FC, - /// - /// The Font Awesome "behance" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "behance" })] - Behance = 0xF1B4, - - /// - /// The Font Awesome "square-behance" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square behance" })] - BehanceSquare = 0xF1B5, - /// /// The Font Awesome "bell" icon unicode character. /// @@ -1115,13 +880,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Sports + Fitness", "Users + People" })] Biking = 0xF84A, - /// - /// The Font Awesome "bimobject" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bimobject" })] - Bimobject = 0xF378, - /// /// The Font Awesome "binoculars" icon unicode character. /// @@ -1143,21 +901,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Childhood", "Food + Beverage", "Maps", "Social" })] BirthdayCake = 0xF1FD, - /// - /// The Font Awesome "bitbucket" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bitbucket", "atlassian", "bitbucket-square", "git" })] - Bitbucket = 0xF171, - - /// - /// The Font Awesome "bitcoin" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bitcoin" })] - [FontAwesomeCategoriesAttribute(new[] { "Money", "Shopping" })] - Bitcoin = 0xF379, - /// /// The Font Awesome "bitcoin-sign" icon unicode character. /// @@ -1165,27 +908,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] BitcoinSign = 0xE0B4, - /// - /// The Font Awesome "bity" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bity" })] - Bity = 0xF37A, - - /// - /// The Font Awesome "blackberry" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "blackberry" })] - Blackberry = 0xF37B, - - /// - /// The Font Awesome "black-tie" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "black tie" })] - BlackTie = 0xF27E, - /// /// The Font Awesome "blender" icon unicode character. /// @@ -1214,36 +936,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Writing" })] Blog = 0xF781, - /// - /// The Font Awesome "blogger" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "blogger" })] - Blogger = 0xF37C, - - /// - /// The Font Awesome "blogger-b" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "blogger b" })] - BloggerB = 0xF37D, - - /// - /// The Font Awesome "bluetooth" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bluetooth", "signal" })] - [FontAwesomeCategoriesAttribute(new[] { "Connectivity" })] - Bluetooth = 0xF293, - - /// - /// The Font Awesome "bluetooth-b" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bluetooth b" })] - [FontAwesomeCategoriesAttribute(new[] { "Communication" })] - BluetoothB = 0xF294, - /// /// The Font Awesome "bold" icon unicode character. /// @@ -1342,13 +1034,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion" })] BookTanakh = 0xF827, - /// - /// The Font Awesome "bootstrap" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "bootstrap" })] - Bootstrap = 0xF836, - /// /// The Font Awesome "border-all" icon unicode character. /// @@ -1552,14 +1237,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Construction", "Design", "Editing" })] Brush = 0xF55D, - /// - /// The Font Awesome "btc" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "btc" })] - [FontAwesomeCategoriesAttribute(new[] { "Money", "Shopping" })] - Btc = 0xF15A, - /// /// The Font Awesome "bucket" icon unicode character. /// @@ -1567,13 +1244,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Camping", "Childhood", "Construction", "Humanitarian" })] Bucket = 0xE4CF, - /// - /// The Font Awesome "buffer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "buffer" })] - Buffer = 0xF837, - /// /// The Font Awesome "bug" icon unicode character. /// @@ -1700,13 +1370,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Energy", "Humanitarian", "Medical + Health", "Science", "Sports + Fitness" })] Burn = 0xF46A, - /// - /// The Font Awesome "buromobelexperte" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "buromobelexperte" })] - Buromobelexperte = 0xF37F, - /// /// The Font Awesome "burst" icon unicode character. /// @@ -1735,20 +1398,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business" })] BusinessTime = 0xF64A, - /// - /// The Font Awesome "buy-n-large" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "buy n large" })] - BuyNLarge = 0xF8A6, - - /// - /// The Font Awesome "buysellads" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "buysellads" })] - Buysellads = 0xF20D, - /// /// The Font Awesome "calculator" icon unicode character. /// @@ -1840,13 +1489,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping" })] Campground = 0xF6BB, - /// - /// The Font Awesome "canadian-maple-leaf" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "canadian maple leaf", "canada", "flag", "flora", "nature", "plant" })] - CanadianMapleLeaf = 0xF785, - /// /// The Font Awesome "candy-cane" icon unicode character. /// @@ -2015,86 +1657,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals", "Halloween" })] Cat = 0xF6BE, - /// - /// The Font Awesome "cc-amazon-pay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc amazon pay" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcAmazonPay = 0xF42D, - - /// - /// The Font Awesome "cc-amex" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc amex", "amex" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcAmex = 0xF1F3, - - /// - /// The Font Awesome "cc-apple-pay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc apple pay" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcApplePay = 0xF416, - - /// - /// The Font Awesome "cc-diners-club" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc diners club" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcDinersClub = 0xF24C, - - /// - /// The Font Awesome "cc-discover" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc discover" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcDiscover = 0xF1F2, - - /// - /// The Font Awesome "cc-jcb" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc jcb" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcJcb = 0xF24B, - - /// - /// The Font Awesome "cc-mastercard" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc mastercard" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcMastercard = 0xF1F1, - - /// - /// The Font Awesome "cc-paypal" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc paypal" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcPaypal = 0xF1F4, - - /// - /// The Font Awesome "cc-stripe" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc stripe" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcStripe = 0xF1F5, - - /// - /// The Font Awesome "cc-visa" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cc visa" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - CcVisa = 0xF1F0, - /// /// The Font Awesome "cedi-sign" icon unicode character. /// @@ -2102,20 +1664,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] CediSign = 0xE0DF, - /// - /// The Font Awesome "centercode" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "centercode" })] - Centercode = 0xF380, - - /// - /// The Font Awesome "centos" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "centos", "linux", "operating system", "os" })] - Centos = 0xF789, - /// /// The Font Awesome "cent-sign" icon unicode character. /// @@ -2389,20 +1937,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Humanitarian", "Users + People" })] Children = 0xE4E1, - /// - /// The Font Awesome "chrome" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "chrome", "browser" })] - Chrome = 0xF268, - - /// - /// The Font Awesome "chromecast" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "chromecast" })] - Chromecast = 0xF838, - /// /// The Font Awesome "church" icon unicode character. /// @@ -2558,13 +2092,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Weather" })] CloudRain = 0xF73D, - /// - /// The Font Awesome "cloudscale" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cloudscale" })] - Cloudscale = 0xF383, - /// /// The Font Awesome "cloud-showers-heavy" icon unicode character. /// @@ -2579,13 +2106,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian", "Weather" })] CloudShowersWater = 0xE4E4, - /// - /// The Font Awesome "cloudsmith" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cloudsmith" })] - Cloudsmith = 0xF384, - /// /// The Font Awesome "cloud-sun" icon unicode character. /// @@ -2608,13 +2128,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Connectivity" })] CloudUploadAlt = 0xF382, - /// - /// The Font Awesome "cloudversify" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cloudversify" })] - Cloudversify = 0xF385, - /// /// The Font Awesome "clover" icon unicode character. /// @@ -2671,13 +2184,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding" })] CodeMerge = 0xF387, - /// - /// The Font Awesome "codepen" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "codepen" })] - Codepen = 0xF1CB, - /// /// The Font Awesome "code-pull-request" icon unicode character. /// @@ -2685,13 +2191,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding" })] CodePullRequest = 0xE13C, - /// - /// The Font Awesome "codiepie" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "codiepie" })] - Codiepie = 0xF284, - /// /// The Font Awesome "mug-saucer" icon unicode character. /// @@ -2839,27 +2338,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel" })] ConciergeBell = 0xF562, - /// - /// The Font Awesome "confluence" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "confluence", "atlassian" })] - Confluence = 0xF78D, - - /// - /// The Font Awesome "connectdevelop" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "connectdevelop" })] - Connectdevelop = 0xF20E, - - /// - /// The Font Awesome "contao" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "contao" })] - Contao = 0xF26D, - /// /// The Font Awesome "cookie" icon unicode character. /// @@ -2888,13 +2366,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business" })] Copyright = 0xF1F9, - /// - /// The Font Awesome "cotton-bureau" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cotton bureau", "clothing", "t-shirts", "tshirts" })] - CottonBureau = 0xF89E, - /// /// The Font Awesome "couch" icon unicode character. /// @@ -2909,111 +2380,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals", "Humanitarian" })] Cow = 0xF6C8, - /// - /// The Font Awesome "cpanel" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cpanel" })] - Cpanel = 0xF388, - - /// - /// The Font Awesome "creative-commons" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons" })] - CreativeCommons = 0xF25E, - - /// - /// The Font Awesome "creative-commons-by" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons by" })] - CreativeCommonsBy = 0xF4E7, - - /// - /// The Font Awesome "creative-commons-nc" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons nc" })] - CreativeCommonsNc = 0xF4E8, - - /// - /// The Font Awesome "creative-commons-nc-eu" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons nc eu" })] - CreativeCommonsNcEu = 0xF4E9, - - /// - /// The Font Awesome "creative-commons-nc-jp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons nc jp" })] - CreativeCommonsNcJp = 0xF4EA, - - /// - /// The Font Awesome "creative-commons-nd" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons nd" })] - CreativeCommonsNd = 0xF4EB, - - /// - /// The Font Awesome "creative-commons-pd" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons pd" })] - CreativeCommonsPd = 0xF4EC, - - /// - /// The Font Awesome "creative-commons-pd-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons pd alt" })] - CreativeCommonsPdAlt = 0xF4ED, - - /// - /// The Font Awesome "creative-commons-remix" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons remix" })] - CreativeCommonsRemix = 0xF4EE, - - /// - /// The Font Awesome "creative-commons-sa" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons sa" })] - CreativeCommonsSa = 0xF4EF, - - /// - /// The Font Awesome "creative-commons-sampling" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons sampling" })] - CreativeCommonsSampling = 0xF4F0, - - /// - /// The Font Awesome "creative-commons-sampling-plus" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons sampling plus" })] - CreativeCommonsSamplingPlus = 0xF4F1, - - /// - /// The Font Awesome "creative-commons-share" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons share" })] - CreativeCommonsShare = 0xF4F2, - - /// - /// The Font Awesome "creative-commons-zero" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "creative commons zero" })] - CreativeCommonsZero = 0xF4F3, - /// /// The Font Awesome "credit-card" icon unicode character. /// @@ -3021,14 +2387,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money", "Shopping" })] CreditCard = 0xF09D, - /// - /// The Font Awesome "critical-role" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "critical role", "dungeons & dragons", "d&d", "dnd", "fantasy", "game", "gaming", "tabletop" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - CriticalRole = 0xF6C9, - /// /// The Font Awesome "crop" icon unicode character. /// @@ -3085,20 +2443,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] CruzeiroSign = 0xE152, - /// - /// The Font Awesome "css3" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "css3", "code" })] - Css3 = 0xF13C, - - /// - /// The Font Awesome "css3-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "css3 alt" })] - Css3Alt = 0xF38B, - /// /// The Font Awesome "cube" icon unicode character. /// @@ -3127,43 +2471,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing", "Files" })] Cut = 0xF0C4, - /// - /// The Font Awesome "cuttlefish" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "cuttlefish" })] - Cuttlefish = 0xF38C, - - /// - /// The Font Awesome "dailymotion" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dailymotion" })] - Dailymotion = 0xF952, - - /// - /// The Font Awesome "d-and-d" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "d and d" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - DAndD = 0xF38D, - - /// - /// The Font Awesome "d-and-d-beyond" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "d and d beyond", "dungeons & dragons", "d&d", "dnd", "fantasy", "gaming", "tabletop" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - DAndDBeyond = 0xF6CA, - - /// - /// The Font Awesome "dashcube" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dashcube" })] - Dashcube = 0xF210, - /// /// The Font Awesome "database" icon unicode character. /// @@ -3178,13 +2485,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Accessibility" })] Deaf = 0xF2A4, - /// - /// The Font Awesome "delicious" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "delicious" })] - Delicious = 0xF1A5, - /// /// The Font Awesome "democrat" icon unicode character. /// @@ -3192,20 +2492,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Political" })] Democrat = 0xF747, - /// - /// The Font Awesome "deploydog" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "deploydog" })] - Deploydog = 0xF38E, - - /// - /// The Font Awesome "deskpro" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "deskpro" })] - Deskpro = 0xF38F, - /// /// The Font Awesome "desktop" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF390. @@ -3214,20 +2500,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] Desktop = 0xF108, - /// - /// The Font Awesome "dev" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dev" })] - Dev = 0xF6CC, - - /// - /// The Font Awesome "deviantart" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "deviantart" })] - Deviantart = 0xF1BD, - /// /// The Font Awesome "dharmachakra" icon unicode character. /// @@ -3235,13 +2507,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion", "Spinners" })] Dharmachakra = 0xF655, - /// - /// The Font Awesome "dhl" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dhl", "dalsey", "hillblom and lynn", "german", "package", "shipping" })] - Dhl = 0xF790, - /// /// The Font Awesome "person-dots-from-line" icon unicode character. /// @@ -3277,13 +2542,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Gaming", "Shapes" })] Diamond = 0xF219, - /// - /// The Font Awesome "diaspora" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "diaspora" })] - Diaspora = 0xF791, - /// /// The Font Awesome "dice" icon unicode character. /// @@ -3347,20 +2605,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] DiceTwo = 0xF528, - /// - /// The Font Awesome "digg" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "digg" })] - Digg = 0xF1A6, - - /// - /// The Font Awesome "digital-ocean" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "digital ocean" })] - DigitalOcean = 0xF391, - /// /// The Font Awesome "tachograph-digital" icon unicode character. /// @@ -3375,20 +2619,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps" })] Directions = 0xF5EB, - /// - /// The Font Awesome "discord" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "discord" })] - Discord = 0xF392, - - /// - /// The Font Awesome "discourse" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "discourse" })] - Discourse = 0xF393, - /// /// The Font Awesome "disease" icon unicode character. /// @@ -3424,20 +2654,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Science" })] Dna = 0xF471, - /// - /// The Font Awesome "dochub" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dochub" })] - Dochub = 0xF394, - - /// - /// The Font Awesome "docker" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "docker" })] - Docker = 0xF395, - /// /// The Font Awesome "dog" icon unicode character. /// @@ -3516,13 +2732,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Devices + Hardware" })] Download = 0xF019, - /// - /// The Font Awesome "draft2digital" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "draft2digital" })] - Draft2digital = 0xF396, - /// /// The Font Awesome "compass-drafting" icon unicode character. /// @@ -3544,27 +2753,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design", "Maps" })] DrawPolygon = 0xF5EE, - /// - /// The Font Awesome "dribbble" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dribbble" })] - Dribbble = 0xF17D, - - /// - /// The Font Awesome "square-dribbble" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square dribbble" })] - DribbbleSquare = 0xF397, - - /// - /// The Font Awesome "dropbox" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dropbox" })] - Dropbox = 0xF16B, - /// /// The Font Awesome "drum" icon unicode character. /// @@ -3586,13 +2774,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage" })] DrumstickBite = 0xF6D7, - /// - /// The Font Awesome "drupal" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "drupal" })] - Drupal = 0xF1A9, - /// /// The Font Awesome "dumbbell" icon unicode character. /// @@ -3621,20 +2802,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Gaming", "Household", "Security" })] Dungeon = 0xF6D9, - /// - /// The Font Awesome "dyalog" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "dyalog" })] - Dyalog = 0xF399, - - /// - /// The Font Awesome "earlybirds" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "earlybirds" })] - Earlybirds = 0xF39A, - /// /// The Font Awesome "earth-oceania" icon unicode character. /// @@ -3642,20 +2809,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel" })] EarthOceania = 0xE47B, - /// - /// The Font Awesome "ebay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ebay" })] - Ebay = 0xF4F4, - - /// - /// The Font Awesome "edge" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "edge", "browser", "ie" })] - Edge = 0xF282, - /// /// The Font Awesome "pen-to-square" icon unicode character. /// @@ -3677,13 +2830,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Media Playback" })] Eject = 0xF052, - /// - /// The Font Awesome "elementor" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "elementor" })] - Elementor = 0xF430, - /// /// The Font Awesome "elevator" icon unicode character. /// @@ -3705,27 +2851,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Editing" })] EllipsisV = 0xF142, - /// - /// The Font Awesome "ello" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ello" })] - Ello = 0xF5F1, - - /// - /// The Font Awesome "ember" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ember" })] - Ember = 0xF423, - - /// - /// The Font Awesome "empire" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "empire" })] - Empire = 0xF1D1, - /// /// The Font Awesome "envelope" icon unicode character. /// @@ -3761,13 +2886,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication" })] EnvelopeSquare = 0xF199, - /// - /// The Font Awesome "envira" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "envira", "leaf" })] - Envira = 0xF299, - /// /// The Font Awesome "equals" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x3D. @@ -3783,21 +2901,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Writing" })] Eraser = 0xF12D, - /// - /// The Font Awesome "erlang" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "erlang" })] - Erlang = 0xF39D, - - /// - /// The Font Awesome "ethereum" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ethereum" })] - [FontAwesomeCategoriesAttribute(new[] { "Money", "Shopping" })] - Ethereum = 0xF42E, - /// /// The Font Awesome "ethernet" icon unicode character. /// @@ -3805,13 +2908,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Connectivity", "Devices + Hardware" })] Ethernet = 0xF796, - /// - /// The Font Awesome "etsy" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "etsy" })] - Etsy = 0xF2D7, - /// /// The Font Awesome "euro-sign" icon unicode character. /// @@ -3819,13 +2915,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] EuroSign = 0xF153, - /// - /// The Font Awesome "evernote" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "evernote" })] - Evernote = 0xF839, - /// /// The Font Awesome "right-left" icon unicode character. /// @@ -3876,13 +2965,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] ExpandArrowsAlt = 0xF31E, - /// - /// The Font Awesome "expeditedssl" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "expeditedssl" })] - Expeditedssl = 0xF23E, - /// /// The Font Awesome "explosion" icon unicode character. /// @@ -3925,34 +3007,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design", "Editing", "Maps", "Photos + Images", "Security" })] EyeSlash = 0xF070, - /// - /// The Font Awesome "facebook" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "facebook", "facebook-official", "social network" })] - Facebook = 0xF09A, - - /// - /// The Font Awesome "facebook-f" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "facebook f", "facebook" })] - FacebookF = 0xF39E, - - /// - /// The Font Awesome "facebook-messenger" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "facebook messenger" })] - FacebookMessenger = 0xF39F, - - /// - /// The Font Awesome "square-facebook" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square facebook", "social network" })] - FacebookSquare = 0xF082, - /// /// The Font Awesome "fan" icon unicode character. /// @@ -3960,14 +3014,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Energy", "Household", "Spinners" })] Fan = 0xF863, - /// - /// The Font Awesome "fantasy-flight-games" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fantasy flight games", "dungeons & dragons", "d&d", "dnd", "fantasy", "game", "gaming", "tabletop" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - FantasyFlightGames = 0xF6DC, - /// /// The Font Awesome "backward-fast" icon unicode character. /// @@ -4017,20 +3063,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals", "Nature" })] FeatherAlt = 0xF56B, - /// - /// The Font Awesome "fedex" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fedex", "federal express", "package", "shipping" })] - Fedex = 0xF797, - - /// - /// The Font Awesome "fedora" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fedora", "linux", "operating system", "os" })] - Fedora = 0xF798, - /// /// The Font Awesome "person-dress" icon unicode character. /// @@ -4052,13 +3084,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps", "Transportation" })] FighterJet = 0xF0FB, - /// - /// The Font Awesome "figma" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "figma", "app", "design", "interface" })] - Figma = 0xF799, - /// /// The Font Awesome "file" icon unicode character. /// @@ -4346,20 +3371,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding", "Maps" })] FireExtinguisher = 0xF134, - /// - /// The Font Awesome "firefox" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "firefox", "browser" })] - Firefox = 0xF269, - - /// - /// The Font Awesome "firefox-browser" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "firefox browser", "browser" })] - FirefoxBrowser = 0xF907, - /// /// The Font Awesome "kit-medical" icon unicode character. /// @@ -4367,27 +3378,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Camping", "Medical + Health" })] FirstAid = 0xF479, - /// - /// The Font Awesome "firstdraft" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "firstdraft" })] - Firstdraft = 0xF3A1, - - /// - /// The Font Awesome "first-order" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "first order" })] - FirstOrder = 0xF2B0, - - /// - /// The Font Awesome "first-order-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "first order alt" })] - FirstOrderAlt = 0xF50A, - /// /// The Font Awesome "fish" icon unicode character. /// @@ -4444,20 +3434,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Science" })] FlaskVial = 0xE4F3, - /// - /// The Font Awesome "flickr" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "flickr" })] - Flickr = 0xF16E, - - /// - /// The Font Awesome "flipboard" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "flipboard" })] - Flipboard = 0xF44D, - /// /// The Font Awesome "florin-sign" icon unicode character. /// @@ -4472,13 +3448,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] Flushed = 0xF579, - /// - /// The Font Awesome "fly" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fly" })] - Fly = 0xF417, - /// /// The Font Awesome "folder" icon unicode character. /// @@ -4535,13 +3504,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding", "Design" })] FontAwesome = 0xF2B4, - /// - /// The Font Awesome "square-font-awesome-stroke" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square font awesome stroke" })] - FontAwesomeAlt = 0xF35C, - /// /// The Font Awesome "font-awesome" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF2B4. @@ -4558,20 +3520,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding", "Design" })] FontAwesomeLogoFull = 0xF4E6, - /// - /// The Font Awesome "fonticons" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fonticons" })] - Fonticons = 0xF280, - - /// - /// The Font Awesome "fonticons-fi" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fonticons fi" })] - FonticonsFi = 0xF3A2, - /// /// The Font Awesome "football" icon unicode character. /// @@ -4579,27 +3527,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] FootballBall = 0xF44E, - /// - /// The Font Awesome "fort-awesome" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fort awesome", "castle" })] - FortAwesome = 0xF286, - - /// - /// The Font Awesome "fort-awesome-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fort awesome alt", "castle" })] - FortAwesomeAlt = 0xF3A3, - - /// - /// The Font Awesome "forumbee" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "forumbee" })] - Forumbee = 0xF211, - /// /// The Font Awesome "forward" icon unicode character. /// @@ -4607,13 +3534,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Media Playback" })] Forward = 0xF04E, - /// - /// The Font Awesome "foursquare" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "foursquare" })] - Foursquare = 0xF180, - /// /// The Font Awesome "franc-sign" icon unicode character. /// @@ -4621,20 +3541,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] FrancSign = 0xE18F, - /// - /// The Font Awesome "freebsd" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "freebsd" })] - Freebsd = 0xF3A4, - - /// - /// The Font Awesome "free-code-camp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "free code camp" })] - FreeCodeCamp = 0xF2C5, - /// /// The Font Awesome "frog" icon unicode character. /// @@ -4656,13 +3562,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] FrownOpen = 0xF57A, - /// - /// The Font Awesome "fulcrum" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "fulcrum" })] - Fulcrum = 0xF50B, - /// /// The Font Awesome "filter-circle-dollar" icon unicode character. /// @@ -4677,22 +3576,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] Futbol = 0xF1E3, - /// - /// The Font Awesome "galactic-republic" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "galactic republic", "politics", "star wars" })] - [FontAwesomeCategoriesAttribute(new[] { "Science Fiction" })] - GalacticRepublic = 0xF50C, - - /// - /// The Font Awesome "galactic-senate" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "galactic senate", "star wars" })] - [FontAwesomeCategoriesAttribute(new[] { "Science Fiction" })] - GalacticSenate = 0xF50D, - /// /// The Font Awesome "gamepad" icon unicode character. /// @@ -4749,29 +3632,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Genders" })] Genderless = 0xF22D, - /// - /// The Font Awesome "get-pocket" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "get pocket" })] - GetPocket = 0xF265, - - /// - /// The Font Awesome "gg" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gg" })] - [FontAwesomeCategoriesAttribute(new[] { "Money" })] - Gg = 0xF260, - - /// - /// The Font Awesome "gg-circle" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gg circle" })] - [FontAwesomeCategoriesAttribute(new[] { "Money" })] - GgCircle = 0xF261, - /// /// The Font Awesome "ghost" icon unicode character. /// @@ -4793,69 +3653,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Holidays", "Shopping" })] Gifts = 0xF79C, - /// - /// The Font Awesome "git" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "git" })] - Git = 0xF1D3, - - /// - /// The Font Awesome "git-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "git alt" })] - GitAlt = 0xF841, - - /// - /// The Font Awesome "github" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "github", "octocat" })] - Github = 0xF09B, - - /// - /// The Font Awesome "github-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "github alt", "octocat" })] - GithubAlt = 0xF113, - - /// - /// The Font Awesome "square-github" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square github", "octocat" })] - GithubSquare = 0xF092, - - /// - /// The Font Awesome "gitkraken" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gitkraken" })] - Gitkraken = 0xF3A6, - - /// - /// The Font Awesome "gitlab" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gitlab", "axosoft" })] - Gitlab = 0xF296, - - /// - /// The Font Awesome "square-git" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square git" })] - GitSquare = 0xF1D2, - - /// - /// The Font Awesome "gitter" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gitter" })] - Gitter = 0xF426, - /// /// The Font Awesome "champagne-glasses" icon unicode character. /// @@ -4905,20 +3702,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage" })] GlassWhiskey = 0xF7A0, - /// - /// The Font Awesome "glide" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "glide" })] - Glide = 0xF2A5, - - /// - /// The Font Awesome "glide-g" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "glide g" })] - GlideG = 0xF2A6, - /// /// The Font Awesome "globe" icon unicode character. /// @@ -4954,13 +3737,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel" })] GlobeEurope = 0xF7A2, - /// - /// The Font Awesome "gofore" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gofore" })] - Gofore = 0xF3A7, - /// /// The Font Awesome "golf-ball-tee" icon unicode character. /// @@ -4968,70 +3744,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] GolfBall = 0xF450, - /// - /// The Font Awesome "goodreads" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "goodreads" })] - Goodreads = 0xF3A8, - - /// - /// The Font Awesome "goodreads-g" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "goodreads g" })] - GoodreadsG = 0xF3A9, - - /// - /// The Font Awesome "google" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "google" })] - Google = 0xF1A0, - - /// - /// The Font Awesome "google-drive" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "google drive" })] - GoogleDrive = 0xF3AA, - - /// - /// The Font Awesome "google-play" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "google play" })] - GooglePlay = 0xF3AB, - - /// - /// The Font Awesome "google-plus" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "google plus", "google-plus-circle", "google-plus-official" })] - GooglePlus = 0xF2B3, - - /// - /// The Font Awesome "google-plus-g" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "google plus g", "google-plus", "social network" })] - GooglePlusG = 0xF0D5, - - /// - /// The Font Awesome "square-google-plus" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square google plus", "social network" })] - GooglePlusSquare = 0xF0D4, - - /// - /// The Font Awesome "google-wallet" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "google wallet" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - GoogleWallet = 0xF1EE, - /// /// The Font Awesome "gopuram" icon unicode character. /// @@ -5046,20 +3758,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Clothing + Fashion", "Education", "Maps" })] GraduationCap = 0xF19D, - /// - /// The Font Awesome "gratipay" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gratipay", "favorite", "heart", "like", "love" })] - Gratipay = 0xF184, - - /// - /// The Font Awesome "grav" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "grav" })] - Grav = 0xF2D6, - /// /// The Font Awesome "greater-than" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x3E. @@ -5173,13 +3871,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] GrinWink = 0xF58C, - /// - /// The Font Awesome "gripfire" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gripfire" })] - Gripfire = 0xF3AC, - /// /// The Font Awesome "grip" icon unicode character. /// @@ -5215,13 +3906,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Marketing" })] GroupArrowsRotate = 0xE4F6, - /// - /// The Font Awesome "grunt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "grunt" })] - Grunt = 0xF3AD, - /// /// The Font Awesome "guarani-sign" icon unicode character. /// @@ -5236,13 +3920,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Music + Audio" })] Guitar = 0xF7A6, - /// - /// The Font Awesome "gulp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "gulp" })] - Gulp = 0xF3AE, - /// /// The Font Awesome "gun" icon unicode character. /// @@ -5250,27 +3927,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Security" })] Gun = 0xE19B, - /// - /// The Font Awesome "hacker-news" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hacker news" })] - HackerNews = 0xF1D4, - - /// - /// The Font Awesome "square-hacker-news" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square hacker news" })] - HackerNewsSquare = 0xF3AF, - - /// - /// The Font Awesome "hackerrank" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hackerrank" })] - Hackerrank = 0xF5F7, - /// /// The Font Awesome "burger" icon unicode character. /// @@ -5734,20 +4390,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals" })] Hippo = 0xF6ED, - /// - /// The Font Awesome "hips" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hips" })] - Hips = 0xF452, - - /// - /// The Font Awesome "hire-a-helper" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hire a helper" })] - HireAHelper = 0xF3B0, - /// /// The Font Awesome "clock-rotate-left" icon unicode character. /// @@ -5776,20 +4418,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Maps" })] Home = 0xF015, - /// - /// The Font Awesome "hooli" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hooli" })] - Hooli = 0xF427, - - /// - /// The Font Awesome "hornbill" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hornbill" })] - Hornbill = 0xF592, - /// /// The Font Awesome "horse" icon unicode character. /// @@ -5847,13 +4475,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Travel + Hotel" })] Hotel = 0xF594, - /// - /// The Font Awesome "hotjar" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hotjar" })] - Hotjar = 0xF3B1, - /// /// The Font Awesome "hot-tub-person" icon unicode character. /// @@ -6043,13 +4664,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Household", "Users + People" })] HouseUser = 0xE1B0, - /// - /// The Font Awesome "houzz" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "houzz" })] - Houzz = 0xF27C, - /// /// The Font Awesome "hryvnia-sign" icon unicode character. /// @@ -6064,20 +4678,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Alphabet", "Maps", "Medical + Health" })] HSquare = 0xF0FD, - /// - /// The Font Awesome "html5" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "html5" })] - Html5 = 0xF13B, - - /// - /// The Font Awesome "hubspot" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "hubspot" })] - Hubspot = 0xF3B2, - /// /// The Font Awesome "hurricane" icon unicode character. /// @@ -6134,13 +4734,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Security", "Users + People" })] IdCardAlt = 0xF47F, - /// - /// The Font Awesome "ideal" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ideal" })] - Ideal = 0xF913, - /// /// The Font Awesome "igloo" icon unicode character. /// @@ -6162,13 +4755,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps", "Photos + Images", "Social" })] Images = 0xF302, - /// - /// The Font Awesome "imdb" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "imdb" })] - Imdb = 0xF2D8, - /// /// The Font Awesome "inbox" icon unicode character. /// @@ -6218,48 +4804,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Maps" })] InfoCircle = 0xF05A, - /// - /// The Font Awesome "instagram" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "instagram" })] - Instagram = 0xF16D, - - /// - /// The Font Awesome "square-instagram" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square instagram" })] - InstagramSquare = 0xF955, - - /// - /// The Font Awesome "intercom" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "intercom", "app", "customer", "messenger" })] - Intercom = 0xF7AF, - - /// - /// The Font Awesome "internet-explorer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "internet explorer", "browser", "ie" })] - InternetExplorer = 0xF26B, - - /// - /// The Font Awesome "invision" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "invision", "app", "design", "interface" })] - Invision = 0xF7B0, - - /// - /// The Font Awesome "ioxhost" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ioxhost" })] - Ioxhost = 0xF208, - /// /// The Font Awesome "italic" icon unicode character. /// @@ -6267,27 +4811,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] Italic = 0xF033, - /// - /// The Font Awesome "itch-io" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "itch io" })] - ItchIo = 0xF83A, - - /// - /// The Font Awesome "itunes" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "itunes" })] - Itunes = 0xF3B4, - - /// - /// The Font Awesome "itunes-note" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "itunes note" })] - ItunesNote = 0xF3B5, - /// /// The Font Awesome "jar" icon unicode character. /// @@ -6302,13 +4825,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Household", "Humanitarian" })] JarWheat = 0xE517, - /// - /// The Font Awesome "java" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "java" })] - Java = 0xF4E4, - /// /// The Font Awesome "jedi" icon unicode character. /// @@ -6316,21 +4832,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion", "Science Fiction" })] Jedi = 0xF669, - /// - /// The Font Awesome "jedi-order" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "jedi order", "star wars" })] - [FontAwesomeCategoriesAttribute(new[] { "Science Fiction" })] - JediOrder = 0xF50E, - - /// - /// The Font Awesome "jenkins" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "jenkins" })] - Jenkins = 0xF3B6, - /// /// The Font Awesome "jet-fighter-up" icon unicode character. /// @@ -6338,20 +4839,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Transportation" })] JetFighterUp = 0xE518, - /// - /// The Font Awesome "jira" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "jira", "atlassian" })] - Jira = 0xF7B1, - - /// - /// The Font Awesome "joget" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "joget" })] - Joget = 0xF3B7, - /// /// The Font Awesome "joint" icon unicode character. /// @@ -6359,13 +4846,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] Joint = 0xF595, - /// - /// The Font Awesome "joomla" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "joomla" })] - Joomla = 0xF1AA, - /// /// The Font Awesome "book-journal-whills" icon unicode character. /// @@ -6373,27 +4853,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion", "Science Fiction" })] JournalWhills = 0xF66A, - /// - /// The Font Awesome "js" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "js" })] - Js = 0xF3B8, - - /// - /// The Font Awesome "jsfiddle" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "jsfiddle" })] - Jsfiddle = 0xF1CC, - - /// - /// The Font Awesome "square-js" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square js" })] - JsSquare = 0xF3B9, - /// /// The Font Awesome "jug-detergent" icon unicode character. /// @@ -6408,13 +4867,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Religion" })] Kaaba = 0xF66B, - /// - /// The Font Awesome "kaggle" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "kaggle" })] - Kaggle = 0xF5FA, - /// /// The Font Awesome "key" icon unicode character. /// @@ -6422,13 +4874,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps", "Security", "Shopping", "Travel + Hotel" })] Key = 0xF084, - /// - /// The Font Awesome "keybase" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "keybase" })] - Keybase = 0xF4F5, - /// /// The Font Awesome "keyboard" icon unicode character. /// @@ -6436,13 +4881,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding", "Devices + Hardware", "Writing" })] Keyboard = 0xF11C, - /// - /// The Font Awesome "keycdn" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "keycdn" })] - Keycdn = 0xF3BA, - /// /// The Font Awesome "khanda" icon unicode character. /// @@ -6450,20 +4888,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion" })] Khanda = 0xF66D, - /// - /// The Font Awesome "kickstarter" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "kickstarter" })] - Kickstarter = 0xF3BB, - - /// - /// The Font Awesome "kickstarter-k" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "kickstarter k" })] - KickstarterK = 0xF3BC, - /// /// The Font Awesome "kip-sign" icon unicode character. /// @@ -6506,13 +4930,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals" })] KiwiBird = 0xF535, - /// - /// The Font Awesome "korvue" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "korvue" })] - Korvue = 0xF42F, - /// /// The Font Awesome "landmark" icon unicode character. /// @@ -6576,13 +4993,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] LaptopMedical = 0xF812, - /// - /// The Font Awesome "laravel" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "laravel" })] - Laravel = 0xF3BD, - /// /// The Font Awesome "lari-sign" icon unicode character. /// @@ -6590,20 +5000,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] LariSign = 0xE1C8, - /// - /// The Font Awesome "lastfm" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "lastfm" })] - Lastfm = 0xF202, - - /// - /// The Font Awesome "square-lastfm" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square lastfm" })] - LastfmSquare = 0xF203, - /// /// The Font Awesome "face-laugh" icon unicode character. /// @@ -6646,13 +5042,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Charity", "Energy", "Fruits + Vegetables", "Maps", "Nature" })] Leaf = 0xF06C, - /// - /// The Font Awesome "leanpub" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "leanpub" })] - Leanpub = 0xF212, - /// /// The Font Awesome "lemon" icon unicode character. /// @@ -6660,13 +5049,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Fruits + Vegetables", "Maps" })] Lemon = 0xF094, - /// - /// The Font Awesome "less" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "less" })] - Less = 0xF41D, - /// /// The Font Awesome "less-than" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x3C. @@ -6710,13 +5092,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Energy", "Household", "Maps", "Marketing" })] Lightbulb = 0xF0EB, - /// - /// The Font Awesome "line" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "line" })] - Line = 0xF3C0, - /// /// The Font Awesome "lines-leaning" icon unicode character. /// @@ -6731,34 +5106,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Editing" })] Link = 0xF0C1, - /// - /// The Font Awesome "linkedin" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "linkedin", "linkedin-square" })] - Linkedin = 0xF08C, - - /// - /// The Font Awesome "linkedin-in" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "linkedin in", "linkedin" })] - LinkedinIn = 0xF0E1, - - /// - /// The Font Awesome "linode" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "linode" })] - Linode = 0xF2B8, - - /// - /// The Font Awesome "linux" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "linux", "tux" })] - Linux = 0xF17C, - /// /// The Font Awesome "lira-sign" icon unicode character. /// @@ -6899,20 +5246,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] LungsVirus = 0xE067, - /// - /// The Font Awesome "lyft" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "lyft" })] - Lyft = 0xF3C3, - - /// - /// The Font Awesome "magento" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "magento" })] - Magento = 0xF3C4, - /// /// The Font Awesome "wand-magic" icon unicode character. /// @@ -6948,13 +5281,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] MailBulk = 0xF674, - /// - /// The Font Awesome "mailchimp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mailchimp" })] - Mailchimp = 0xF59E, - /// /// The Font Awesome "person" icon unicode character. /// @@ -6969,13 +5295,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] ManatSign = 0xE1D5, - /// - /// The Font Awesome "mandalorian" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mandalorian" })] - Mandalorian = 0xF50F, - /// /// The Font Awesome "map" icon unicode character. /// @@ -7025,13 +5344,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Camping", "Maps", "Nature" })] MapSigns = 0xF277, - /// - /// The Font Awesome "markdown" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "markdown" })] - Markdown = 0xF60F, - /// /// The Font Awesome "marker" icon unicode character. /// @@ -7102,13 +5414,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health" })] MaskVentilator = 0xE524, - /// - /// The Font Awesome "mastodon" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mastodon" })] - Mastodon = 0xF4F6, - /// /// The Font Awesome "mattress-pillow" icon unicode character. /// @@ -7116,20 +5421,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Camping", "Household", "Humanitarian" })] MattressPillow = 0xE525, - /// - /// The Font Awesome "maxcdn" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "maxcdn" })] - Maxcdn = 0xF136, - - /// - /// The Font Awesome "mdb" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mdb" })] - Mdb = 0xF8CA, - /// /// The Font Awesome "medal" icon unicode character. /// @@ -7137,28 +5428,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] Medal = 0xF5A2, - /// - /// The Font Awesome "medapps" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "medapps" })] - Medapps = 0xF3C6, - - /// - /// The Font Awesome "medium" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "medium" })] - Medium = 0xF23A, - - /// - /// The Font Awesome "medium" icon unicode character. - /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF23A. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "medium" })] - MediumM = 0xF3C7, - /// /// The Font Awesome "suitcase-medical" icon unicode character. /// @@ -7166,27 +5435,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Maps", "Medical + Health" })] Medkit = 0xF0FA, - /// - /// The Font Awesome "medrt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "medrt" })] - Medrt = 0xF3C8, - - /// - /// The Font Awesome "meetup" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "meetup" })] - Meetup = 0xF2E0, - - /// - /// The Font Awesome "megaport" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "megaport" })] - Megaport = 0xF5A3, - /// /// The Font Awesome "face-meh" icon unicode character. /// @@ -7215,13 +5463,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] Memory = 0xF538, - /// - /// The Font Awesome "mendeley" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mendeley" })] - Mendeley = 0xF7B3, - /// /// The Font Awesome "menorah" icon unicode character. /// @@ -7291,13 +5532,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Education", "Humanitarian", "Medical + Health", "Science" })] Microscope = 0xF610, - /// - /// The Font Awesome "microsoft" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "microsoft" })] - Microsoft = 0xF3CA, - /// /// The Font Awesome "mill-sign" icon unicode character. /// @@ -7333,34 +5567,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Clothing + Fashion" })] Mitten = 0xF7B5, - /// - /// The Font Awesome "mix" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mix" })] - Mix = 0xF3CB, - - /// - /// The Font Awesome "mixcloud" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mixcloud" })] - Mixcloud = 0xF289, - - /// - /// The Font Awesome "mixer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mixer" })] - Mixer = 0xF956, - - /// - /// The Font Awesome "mizuni" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "mizuni" })] - Mizuni = 0xF3CC, - /// /// The Font Awesome "mobile" icon unicode character. /// @@ -7396,20 +5602,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Communication", "Devices + Hardware", "Humanitarian" })] MobileScreen = 0xF3CF, - /// - /// The Font Awesome "modx" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "modx" })] - Modx = 0xF285, - - /// - /// The Font Awesome "monero" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "monero" })] - Monero = 0xF3D0, - /// /// The Font Awesome "money-bill" icon unicode character. /// @@ -7592,21 +5784,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] NairaSign = 0xE1F6, - /// - /// The Font Awesome "napster" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "napster" })] - [FontAwesomeCategoriesAttribute(new[] { "Music + Audio" })] - Napster = 0xF3D2, - - /// - /// The Font Awesome "neos" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "neos" })] - Neos = 0xF612, - /// /// The Font Awesome "network-wired" icon unicode character. /// @@ -7628,27 +5805,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps", "Writing" })] Newspaper = 0xF1EA, - /// - /// The Font Awesome "nimblr" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "nimblr" })] - Nimblr = 0xF5A8, - - /// - /// The Font Awesome "node" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "node" })] - Node = 0xF419, - - /// - /// The Font Awesome "node-js" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "node js" })] - NodeJs = 0xF3D3, - /// /// The Font Awesome "notdef" icon unicode character. /// @@ -7670,27 +5826,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] NotesMedical = 0xF481, - /// - /// The Font Awesome "npm" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "npm" })] - Npm = 0xF3D4, - - /// - /// The Font Awesome "ns8" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ns8" })] - Ns8 = 0xF3D5, - - /// - /// The Font Awesome "nutritionix" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "nutritionix" })] - Nutritionix = 0xF3D6, - /// /// The Font Awesome "object-group" icon unicode character. /// @@ -7705,20 +5840,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design" })] ObjectUngroup = 0xF248, - /// - /// The Font Awesome "odnoklassniki" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "odnoklassniki" })] - Odnoklassniki = 0xF263, - - /// - /// The Font Awesome "square-odnoklassniki" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square odnoklassniki" })] - OdnoklassnikiSquare = 0xF264, - /// /// The Font Awesome "oil-can" icon unicode character. /// @@ -7733,14 +5854,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Energy", "Humanitarian" })] OilWell = 0xE532, - /// - /// The Font Awesome "old-republic" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "old republic", "politics", "star wars" })] - [FontAwesomeCategoriesAttribute(new[] { "Science Fiction" })] - OldRepublic = 0xF510, - /// /// The Font Awesome "om" icon unicode character. /// @@ -7748,48 +5861,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion" })] Om = 0xF679, - /// - /// The Font Awesome "opencart" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "opencart" })] - Opencart = 0xF23D, - - /// - /// The Font Awesome "openid" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "openid" })] - Openid = 0xF19B, - - /// - /// The Font Awesome "opera" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "opera" })] - Opera = 0xF26A, - - /// - /// The Font Awesome "optin-monster" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "optin monster" })] - OptinMonster = 0xF23C, - - /// - /// The Font Awesome "orcid" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "orcid" })] - Orcid = 0xF8D2, - - /// - /// The Font Awesome "osi" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "osi" })] - Osi = 0xF41A, - /// /// The Font Awesome "otter" icon unicode character. /// @@ -7804,20 +5875,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] Outdent = 0xF03B, - /// - /// The Font Awesome "page4" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "page4" })] - Page4 = 0xF3D7, - - /// - /// The Font Awesome "pagelines" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pagelines", "eco", "flora", "leaf", "leaves", "nature", "plant", "tree" })] - Pagelines = 0xF18C, - /// /// The Font Awesome "pager" icon unicode character. /// @@ -7846,13 +5903,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design", "Spinners" })] Palette = 0xF53F, - /// - /// The Font Awesome "palfed" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "palfed" })] - Palfed = 0xF3D8, - /// /// The Font Awesome "pallet" icon unicode character. /// @@ -7923,13 +5973,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Files" })] Paste = 0xF0EA, - /// - /// The Font Awesome "patreon" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "patreon" })] - Patreon = 0xF3D9, - /// /// The Font Awesome "pause" icon unicode character. /// @@ -7951,14 +5994,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals", "Maps" })] Paw = 0xF1B0, - /// - /// The Font Awesome "paypal" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "paypal" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - Paypal = 0xF1ED, - /// /// The Font Awesome "peace" icon unicode character. /// @@ -8093,13 +6128,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Mathematics", "Money", "Punctuation + Symbols" })] Percentage = 0xF541, - /// - /// The Font Awesome "periscope" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "periscope" })] - Periscope = 0xF3DA, - /// /// The Font Awesome "person-arrow-down-to-line" icon unicode character. /// @@ -8338,27 +6366,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] PesoSign = 0xE222, - /// - /// The Font Awesome "phabricator" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "phabricator" })] - Phabricator = 0xF3DB, - - /// - /// The Font Awesome "phoenix-framework" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "phoenix framework" })] - PhoenixFramework = 0xF3DC, - - /// - /// The Font Awesome "phoenix-squadron" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "phoenix squadron" })] - PhoenixSquadron = 0xF511, - /// /// The Font Awesome "phone" icon unicode character. /// @@ -8408,41 +6415,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Files", "Film + Video", "Photos + Images", "Social" })] PhotoVideo = 0xF87C, - /// - /// The Font Awesome "php" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "php" })] - Php = 0xF457, - - /// - /// The Font Awesome "pied-piper" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pied piper" })] - PiedPiper = 0xF2AE, - - /// - /// The Font Awesome "pied-piper-alt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pied piper alt" })] - PiedPiperAlt = 0xF1A8, - - /// - /// The Font Awesome "pied-piper-hat" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pied piper hat", "clothing" })] - PiedPiperHat = 0xF4E5, - - /// - /// The Font Awesome "pied-piper-pp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pied piper pp" })] - PiedPiperPp = 0xF1A7, - /// /// The Font Awesome "piedpipersquare" icon unicode character. /// @@ -8463,27 +6435,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Science" })] Pills = 0xF484, - /// - /// The Font Awesome "pinterest" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pinterest" })] - Pinterest = 0xF0D2, - - /// - /// The Font Awesome "pinterest-p" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pinterest p" })] - PinterestP = 0xF231, - - /// - /// The Font Awesome "square-pinterest" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square pinterest" })] - PinterestSquare = 0xF0D3, - /// /// The Font Awesome "pizza-slice" icon unicode character. /// @@ -8589,14 +6540,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Media Playback" })] PlayCircle = 0xF144, - /// - /// The Font Awesome "playstation" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "playstation" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - Playstation = 0xF3DF, - /// /// The Font Awesome "plug" icon unicode character. /// @@ -8787,13 +6730,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] Procedures = 0xF487, - /// - /// The Font Awesome "product-hunt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "product hunt" })] - ProductHunt = 0xF288, - /// /// The Font Awesome "diagram-project" icon unicode character. /// @@ -8815,13 +6751,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Household", "Humanitarian" })] PumpSoap = 0xE06B, - /// - /// The Font Awesome "pushed" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "pushed" })] - Pushed = 0xF3E1, - /// /// The Font Awesome "puzzle-piece" icon unicode character. /// @@ -8829,20 +6758,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Gaming" })] PuzzlePiece = 0xF12E, - /// - /// The Font Awesome "python" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "python" })] - Python = 0xF3E2, - - /// - /// The Font Awesome "qq" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "qq" })] - Qq = 0xF1D6, - /// /// The Font Awesome "qrcode" icon unicode character. /// @@ -8872,20 +6787,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] Quidditch = 0xF458, - /// - /// The Font Awesome "quinscape" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "quinscape" })] - Quinscape = 0xF459, - - /// - /// The Font Awesome "quora" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "quora" })] - Quora = 0xF2C4, - /// /// The Font Awesome "quote-left" icon unicode character. /// @@ -8949,48 +6850,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Marketing", "Sports + Fitness" })] RankingStar = 0xE561, - /// - /// The Font Awesome "raspberry-pi" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "raspberry pi" })] - RaspberryPi = 0xF7BB, - - /// - /// The Font Awesome "ravelry" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ravelry" })] - Ravelry = 0xF2D9, - - /// - /// The Font Awesome "react" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "react" })] - React = 0xF41B, - - /// - /// The Font Awesome "reacteurope" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "reacteurope" })] - Reacteurope = 0xF75D, - - /// - /// The Font Awesome "readme" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "readme" })] - Readme = 0xF4D5, - - /// - /// The Font Awesome "rebel" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "rebel" })] - Rebel = 0xF1D0, - /// /// The Font Awesome "receipt" icon unicode character. /// @@ -9012,34 +6871,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Maps" })] Recycle = 0xF1B8, - /// - /// The Font Awesome "reddit" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "reddit" })] - Reddit = 0xF1A1, - - /// - /// The Font Awesome "reddit-alien" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "reddit alien" })] - RedditAlien = 0xF281, - - /// - /// The Font Awesome "square-reddit" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square reddit" })] - RedditSquare = 0xF1A2, - - /// - /// The Font Awesome "redhat" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "redhat", "linux", "operating system", "os" })] - Redhat = 0xF7BC, - /// /// The Font Awesome "arrow-rotate-right" icon unicode character. /// @@ -9054,13 +6885,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] RedoAlt = 0xF2F9, - /// - /// The Font Awesome "red-river" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "red river" })] - RedRiver = 0xF3E3, - /// /// The Font Awesome "registered" icon unicode character. /// @@ -9075,13 +6899,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] RemoveFormat = 0xF87D, - /// - /// The Font Awesome "renren" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "renren" })] - Renren = 0xF18B, - /// /// The Font Awesome "repeat" icon unicode character. /// @@ -9103,13 +6920,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ReplyAll = 0xF122, - /// - /// The Font Awesome "replyd" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "replyd" })] - Replyd = 0xF3E6, - /// /// The Font Awesome "republican" icon unicode character. /// @@ -9117,20 +6927,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Political" })] Republican = 0xF75E, - /// - /// The Font Awesome "researchgate" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "researchgate" })] - Researchgate = 0xF4F8, - - /// - /// The Font Awesome "resolving" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "resolving" })] - Resolving = 0xF3E7, - /// /// The Font Awesome "restroom" icon unicode character. /// @@ -9145,13 +6941,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Social" })] Retweet = 0xF079, - /// - /// The Font Awesome "rev" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "rev" })] - Rev = 0xF5B2, - /// /// The Font Awesome "ribbon" icon unicode character. /// @@ -9236,20 +7025,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps", "Science Fiction", "Transportation" })] Rocket = 0xF135, - /// - /// The Font Awesome "rocketchat" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "rocketchat" })] - Rocketchat = 0xF3E8, - - /// - /// The Font Awesome "rockrms" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "rockrms" })] - Rockrms = 0xF3E9, - /// /// The Font Awesome "route" icon unicode character. /// @@ -9257,13 +7032,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Camping", "Maps", "Moving" })] Route = 0xF4D7, - /// - /// The Font Awesome "r-project" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "r project" })] - RProject = 0xF4F7, - /// /// The Font Awesome "rss" icon unicode character. /// @@ -9369,13 +7137,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] SadTear = 0xF5B4, - /// - /// The Font Awesome "safari" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "safari", "browser" })] - Safari = 0xF267, - /// /// The Font Awesome "sailboat" icon unicode character. /// @@ -9383,20 +7144,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Maritime", "Transportation" })] Sailboat = 0xE445, - /// - /// The Font Awesome "salesforce" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "salesforce" })] - Salesforce = 0xF83B, - - /// - /// The Font Awesome "sass" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sass" })] - Sass = 0xF41E, - /// /// The Font Awesome "satellite" icon unicode character. /// @@ -9418,13 +7165,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Devices + Hardware", "Files" })] Save = 0xF0C7, - /// - /// The Font Awesome "schlix" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "schlix" })] - Schlix = 0xF3EA, - /// /// The Font Awesome "school" icon unicode character. /// @@ -9474,13 +7214,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Construction" })] Screwdriver = 0xF54A, - /// - /// The Font Awesome "scribd" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "scribd" })] - Scribd = 0xF28A, - /// /// The Font Awesome "scroll" icon unicode character. /// @@ -9509,13 +7242,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] SearchDollar = 0xF688, - /// - /// The Font Awesome "searchengin" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "searchengin" })] - Searchengin = 0xF3EB, - /// /// The Font Awesome "magnifying-glass-location" icon unicode character. /// @@ -9551,20 +7277,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Charity", "Energy", "Food + Beverage", "Fruits + Vegetables", "Humanitarian", "Nature", "Science" })] Seedling = 0xF4D8, - /// - /// The Font Awesome "sellcast" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sellcast", "eercast" })] - Sellcast = 0xF2DA, - - /// - /// The Font Awesome "sellsy" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sellsy" })] - Sellsy = 0xF213, - /// /// The Font Awesome "server" icon unicode character. /// @@ -9572,13 +7284,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] Server = 0xF233, - /// - /// The Font Awesome "servicestack" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "servicestack" })] - Servicestack = 0xF3EC, - /// /// The Font Awesome "shapes" icon unicode character. /// @@ -9684,13 +7389,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Logistics", "Shopping" })] ShippingFast = 0xF48B, - /// - /// The Font Awesome "shirtsinbulk" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "shirtsinbulk" })] - Shirtsinbulk = 0xF214, - /// /// The Font Awesome "shoe-prints" icon unicode character. /// @@ -9698,13 +7396,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Clothing + Fashion", "Maps", "Sports + Fitness" })] ShoePrints = 0xF54B, - /// - /// The Font Awesome "shopify" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "shopify" })] - Shopify = 0xF957, - /// /// The Font Awesome "shop-lock" icon unicode character. /// @@ -9740,13 +7431,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] ShopSlash = 0xE070, - /// - /// The Font Awesome "shopware" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "shopware" })] - Shopware = 0xF5B5, - /// /// The Font Awesome "shower" icon unicode character. /// @@ -9817,13 +7501,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] SimCard = 0xF7C4, - /// - /// The Font Awesome "simplybuilt" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "simplybuilt" })] - Simplybuilt = 0xF215, - /// /// The Font Awesome "sink" icon unicode character. /// @@ -9831,13 +7508,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Household" })] Sink = 0xE06D, - /// - /// The Font Awesome "sistrix" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sistrix" })] - Sistrix = 0xF3EE, - /// /// The Font Awesome "sitemap" icon unicode character. /// @@ -9845,13 +7515,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Coding" })] Sitemap = 0xF0E8, - /// - /// The Font Awesome "sith" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sith" })] - Sith = 0xF512, - /// /// The Font Awesome "person-skating" icon unicode character. /// @@ -9859,13 +7522,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Users + People" })] Skating = 0xF7C5, - /// - /// The Font Awesome "sketch" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sketch", "app", "design", "interface" })] - Sketch = 0xF7C6, - /// /// The Font Awesome "person-skiing" icon unicode character. /// @@ -9894,35 +7550,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Alert", "Gaming", "Halloween", "Humanitarian", "Medical + Health", "Science", "Security" })] SkullCrossbones = 0xF714, - /// - /// The Font Awesome "skyatlas" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "skyatlas" })] - Skyatlas = 0xF216, - - /// - /// The Font Awesome "skype" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "skype" })] - Skype = 0xF17E, - - /// - /// The Font Awesome "slack" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "slack", "anchor", "hash", "hashtag" })] - Slack = 0xF198, - - /// - /// The Font Awesome "slack" icon unicode character. - /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF198. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "slack", "anchor", "hash", "hashtag" })] - SlackHash = 0xF3EF, - /// /// The Font Awesome "slash" icon unicode character. /// @@ -9944,13 +7571,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Editing", "Media Playback", "Music + Audio", "Photos + Images" })] SlidersH = 0xF1DE, - /// - /// The Font Awesome "slideshare" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "slideshare" })] - Slideshare = 0xF1E7, - /// /// The Font Awesome "face-smile" icon unicode character. /// @@ -10000,28 +7620,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Communication" })] Sms = 0xF7CD, - /// - /// The Font Awesome "snapchat" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "snapchat" })] - Snapchat = 0xF2AB, - - /// - /// The Font Awesome "snapchat" icon unicode character. - /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF2AB. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "snapchat" })] - SnapchatGhost = 0xF2AC, - - /// - /// The Font Awesome "square-snapchat" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square snapchat" })] - SnapchatSquare = 0xF2AD, - /// /// The Font Awesome "person-snowboarding" icon unicode character. /// @@ -10176,21 +7774,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] SortUp = 0xF0DE, - /// - /// The Font Awesome "soundcloud" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "soundcloud" })] - [FontAwesomeCategoriesAttribute(new[] { "Music + Audio" })] - Soundcloud = 0xF1BE, - - /// - /// The Font Awesome "sourcetree" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sourcetree" })] - Sourcetree = 0xF7D3, - /// /// The Font Awesome "spa" icon unicode character. /// @@ -10205,20 +7788,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Astronomy", "Transportation" })] SpaceShuttle = 0xF197, - /// - /// The Font Awesome "speakap" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "speakap" })] - Speakap = 0xF3F3, - - /// - /// The Font Awesome "speaker-deck" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "speaker deck" })] - SpeakerDeck = 0xF83C, - /// /// The Font Awesome "spell-check" icon unicode character. /// @@ -10247,14 +7816,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design" })] Splotch = 0xF5BC, - /// - /// The Font Awesome "spotify" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "spotify" })] - [FontAwesomeCategoriesAttribute(new[] { "Music + Audio" })] - Spotify = 0xF1BC, - /// /// The Font Awesome "spray-can" icon unicode character. /// @@ -10304,13 +7865,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Mathematics" })] SquareRootAlt = 0xF698, - /// - /// The Font Awesome "squarespace" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "squarespace" })] - Squarespace = 0xF5BE, - /// /// The Font Awesome "square-virus" icon unicode character. /// @@ -10325,27 +7879,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Mathematics" })] SquareXmark = 0xF2D3, - /// - /// The Font Awesome "stack-exchange" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stack exchange" })] - StackExchange = 0xF18D, - - /// - /// The Font Awesome "stack-overflow" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stack overflow" })] - StackOverflow = 0xF16C, - - /// - /// The Font Awesome "stackpath" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stackpath" })] - Stackpath = 0xF842, - /// /// The Font Awesome "staff-snake" icon unicode character. /// @@ -10416,37 +7949,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] StarOfLife = 0xF621, - /// - /// The Font Awesome "staylinked" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "staylinked" })] - Staylinked = 0xF3F5, - - /// - /// The Font Awesome "steam" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "steam" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - Steam = 0xF1B6, - - /// - /// The Font Awesome "square-steam" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square steam" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - SteamSquare = 0xF1B7, - - /// - /// The Font Awesome "steam-symbol" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "steam symbol" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - SteamSymbol = 0xF3F6, - /// /// The Font Awesome "backward-step" icon unicode character. /// @@ -10468,13 +7970,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health" })] Stethoscope = 0xF0F1, - /// - /// The Font Awesome "sticker-mule" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "sticker mule" })] - StickerMule = 0xF3F7, - /// /// The Font Awesome "note-sticky" icon unicode character. /// @@ -10531,13 +8026,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] StoreSlash = 0xE071, - /// - /// The Font Awesome "strava" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "strava" })] - Strava = 0xF428, - /// /// The Font Awesome "bars-staggered" icon unicode character. /// @@ -10559,22 +8047,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] Strikethrough = 0xF0CC, - /// - /// The Font Awesome "stripe" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stripe" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - Stripe = 0xF429, - - /// - /// The Font Awesome "stripe-s" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stripe s" })] - [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] - StripeS = 0xF42A, - /// /// The Font Awesome "stroopwafel" icon unicode character. /// @@ -10582,27 +8054,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Spinners" })] Stroopwafel = 0xF551, - /// - /// The Font Awesome "studiovinari" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "studiovinari" })] - Studiovinari = 0xF3F8, - - /// - /// The Font Awesome "stumbleupon" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stumbleupon" })] - Stumbleupon = 0xF1A4, - - /// - /// The Font Awesome "stumbleupon-circle" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "stumbleupon circle" })] - StumbleuponCircle = 0xF1A3, - /// /// The Font Awesome "subscript" icon unicode character. /// @@ -10645,13 +8096,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian", "Weather" })] SunPlantWilt = 0xE57A, - /// - /// The Font Awesome "superpowers" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "superpowers" })] - Superpowers = 0xF2DD, - /// /// The Font Awesome "superscript" icon unicode character. /// @@ -10659,13 +8103,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Mathematics", "Text Formatting" })] Superscript = 0xF12B, - /// - /// The Font Awesome "supple" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "supple" })] - Supple = 0xF3F9, - /// /// The Font Awesome "face-surprise" icon unicode character. /// @@ -10673,13 +8110,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] Surprise = 0xF5C2, - /// - /// The Font Awesome "suse" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "suse", "linux", "operating system", "os" })] - Suse = 0xF7D6, - /// /// The Font Awesome "swatchbook" icon unicode character. /// @@ -10687,13 +8117,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design" })] Swatchbook = 0xF5C3, - /// - /// The Font Awesome "swift" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "swift" })] - Swift = 0xF8E1, - /// /// The Font Awesome "person-swimming" icon unicode character. /// @@ -10708,13 +8131,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel" })] SwimmingPool = 0xF5C5, - /// - /// The Font Awesome "symfony" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "symfony" })] - Symfony = 0xF83D, - /// /// The Font Awesome "synagogue" icon unicode character. /// @@ -10842,13 +8258,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Automotive", "Maps", "Transportation", "Travel + Hotel" })] Taxi = 0xF1BA, - /// - /// The Font Awesome "teamspeak" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "teamspeak" })] - Teamspeak = 0xF4F9, - /// /// The Font Awesome "teeth" icon unicode character. /// @@ -10863,21 +8272,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] TeethOpen = 0xF62F, - /// - /// The Font Awesome "telegram" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "telegram" })] - Telegram = 0xF2C6, - - /// - /// The Font Awesome "telegram" icon unicode character. - /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF2C6. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "telegram" })] - TelegramPlane = 0xF3FE, - /// /// The Font Awesome "temperature-arrow-down" icon unicode character. /// @@ -10906,13 +8300,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Science", "Weather" })] TemperatureLow = 0xF76B, - /// - /// The Font Awesome "tencent-weibo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "tencent weibo" })] - TencentWeibo = 0xF1D5, - /// /// The Font Awesome "tenge-sign" icon unicode character. /// @@ -10997,27 +8384,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Education" })] TheaterMasks = 0xF630, - /// - /// The Font Awesome "themeco" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "themeco" })] - Themeco = 0xF5C6, - - /// - /// The Font Awesome "themeisle" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "themeisle" })] - Themeisle = 0xF2B2, - - /// - /// The Font Awesome "the-red-yeti" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "the red yeti" })] - TheRedYeti = 0xF69D, - /// /// The Font Awesome "thermometer" icon unicode character. /// @@ -11060,13 +8426,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Weather" })] ThermometerThreeQuarters = 0xF2C8, - /// - /// The Font Awesome "think-peaks" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "think peaks" })] - ThinkPeaks = 0xF731, - /// /// The Font Awesome "table-cells-large" icon unicode character. /// @@ -11270,13 +8629,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Transportation" })] Tractor = 0xF722, - /// - /// The Font Awesome "trade-federation" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "trade federation" })] - TradeFederation = 0xF513, - /// /// The Font Awesome "trademark" icon unicode character. /// @@ -11291,14 +8643,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Maps" })] TrafficLight = 0xF637, - /// - /// The Font Awesome "trailer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "trailer", "carry", "haul", "moving", "travel" })] - [FontAwesomeCategoriesAttribute(new[] { "Automotive", "Camping", "Moving" })] - Trailer = 0xF941, - /// /// The Font Awesome "train" icon unicode character. /// @@ -11376,13 +8720,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Travel + Hotel" })] TreeCity = 0xE587, - /// - /// The Font Awesome "trello" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "trello", "atlassian" })] - Trello = 0xF181, - /// /// The Font Awesome "tripadvisor" icon unicode character. /// @@ -11501,20 +8838,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Communication", "Maps" })] Tty = 0xF1E4, - /// - /// The Font Awesome "tumblr" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "tumblr" })] - Tumblr = 0xF173, - - /// - /// The Font Awesome "square-tumblr" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square tumblr" })] - TumblrSquare = 0xF174, - /// /// The Font Awesome "turkish-lira-sign" icon unicode character. /// @@ -11529,63 +8852,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware", "Film + Video", "Household", "Travel + Hotel" })] Tv = 0xF26C, - /// - /// The Font Awesome "twitch" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "twitch" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - Twitch = 0xF1E8, - - /// - /// The Font Awesome "twitter" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "twitter", "social network", "tweet" })] - Twitter = 0xF099, - - /// - /// The Font Awesome "square-twitter" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square twitter", "social network", "tweet" })] - TwitterSquare = 0xF081, - - /// - /// The Font Awesome "typo3" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "typo3" })] - Typo3 = 0xF42B, - - /// - /// The Font Awesome "uber" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "uber" })] - Uber = 0xF402, - - /// - /// The Font Awesome "ubuntu" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ubuntu", "linux", "operating system", "os" })] - Ubuntu = 0xF7DF, - - /// - /// The Font Awesome "uikit" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "uikit" })] - Uikit = 0xF403, - - /// - /// The Font Awesome "umbraco" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "umbraco" })] - Umbraco = 0xF8E8, - /// /// The Font Awesome "umbrella" icon unicode character. /// @@ -11621,13 +8887,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] UndoAlt = 0xF2EA, - /// - /// The Font Awesome "uniregistry" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "uniregistry" })] - Uniregistry = 0xF404, - /// /// The Font Awesome "unity" icon unicode character. /// @@ -11669,13 +8928,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Security" })] UnlockAlt = 0xF13E, - /// - /// The Font Awesome "untappd" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "untappd" })] - Untappd = 0xF405, - /// /// The Font Awesome "upload" icon unicode character. /// @@ -11683,20 +8935,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Devices + Hardware" })] Upload = 0xF093, - /// - /// The Font Awesome "ups" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ups", "united parcel service", "package", "shipping" })] - Ups = 0xF7E0, - - /// - /// The Font Awesome "usb" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "usb" })] - Usb = 0xF287, - /// /// The Font Awesome "user" icon unicode character. /// @@ -11921,20 +9159,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserTimes = 0xF235, - /// - /// The Font Awesome "usps" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "usps", "american", "package", "shipping", "usa" })] - Usps = 0xF7E1, - - /// - /// The Font Awesome "ussunnah" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "ussunnah" })] - Ussunnah = 0xF407, - /// /// The Font Awesome "utensils" icon unicode character. /// @@ -11949,13 +9173,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Household", "Maps" })] UtensilSpoon = 0xF2E5, - /// - /// The Font Awesome "vaadin" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vaadin" })] - Vaadin = 0xF408, - /// /// The Font Awesome "vault" icon unicode character. /// @@ -12005,27 +9222,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Clothing + Fashion", "Maps" })] VestPatches = 0xE086, - /// - /// The Font Awesome "viacoin" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "viacoin" })] - Viacoin = 0xF237, - - /// - /// The Font Awesome "viadeo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "viadeo" })] - Viadeo = 0xF2A9, - - /// - /// The Font Awesome "square-viadeo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square viadeo" })] - ViadeoSquare = 0xF2AA, - /// /// The Font Awesome "vial" icon unicode character. /// @@ -12054,13 +9250,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Science" })] VialVirus = 0xE597, - /// - /// The Font Awesome "viber" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "viber" })] - Viber = 0xF409, - /// /// The Font Awesome "video" icon unicode character. /// @@ -12082,34 +9271,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Religion" })] Vihara = 0xF6A7, - /// - /// The Font Awesome "vimeo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vimeo" })] - Vimeo = 0xF40A, - - /// - /// The Font Awesome "square-vimeo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square vimeo" })] - VimeoSquare = 0xF194, - - /// - /// The Font Awesome "vimeo-v" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vimeo v", "vimeo" })] - VimeoV = 0xF27D, - - /// - /// The Font Awesome "vine" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vine" })] - Vine = 0xF1CA, - /// /// The Font Awesome "virus" icon unicode character. /// @@ -12145,20 +9306,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] VirusSlash = 0xE075, - /// - /// The Font Awesome "vk" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vk" })] - Vk = 0xF189, - - /// - /// The Font Awesome "vnv" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vnv" })] - Vnv = 0xF40B, - /// /// The Font Awesome "voicemail" icon unicode character. /// @@ -12222,13 +9369,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] VrCardboard = 0xF729, - /// - /// The Font Awesome "vuejs" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "vuejs" })] - Vuejs = 0xF41F, - /// /// The Font Awesome "walkie-talkie" icon unicode character. /// @@ -12285,27 +9425,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Mathematics" })] WaveSquare = 0xF83E, - /// - /// The Font Awesome "waze" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "waze" })] - Waze = 0xF83F, - - /// - /// The Font Awesome "weebly" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "weebly" })] - Weebly = 0xF5CC, - - /// - /// The Font Awesome "weibo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "weibo" })] - Weibo = 0xF18A, - /// /// The Font Awesome "weight-scale" icon unicode character. /// @@ -12320,27 +9439,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] WeightHanging = 0xF5CD, - /// - /// The Font Awesome "weixin" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "weixin" })] - Weixin = 0xF1D7, - - /// - /// The Font Awesome "whatsapp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "whatsapp" })] - Whatsapp = 0xF232, - - /// - /// The Font Awesome "square-whatsapp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square whatsapp" })] - WhatsappSquare = 0xF40C, - /// /// The Font Awesome "wheat-awn" icon unicode character. /// @@ -12369,13 +9467,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Humanitarian", "Maps", "Medical + Health", "Transportation", "Travel + Hotel", "Users + People" })] WheelchairMove = 0xE2CE, - /// - /// The Font Awesome "whmcs" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "whmcs" })] - Whmcs = 0xF40D, - /// /// The Font Awesome "wifi" icon unicode character. /// @@ -12383,13 +9474,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Connectivity", "Humanitarian", "Maps", "Toggle", "Travel + Hotel" })] Wifi = 0xF1EB, - /// - /// The Font Awesome "wikipedia-w" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wikipedia w" })] - WikipediaW = 0xF266, - /// /// The Font Awesome "wind" icon unicode character. /// @@ -12425,13 +9509,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Coding" })] WindowRestore = 0xF2D2, - /// - /// The Font Awesome "windows" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "windows", "microsoft", "operating system", "os" })] - Windows = 0xF17A, - /// /// The Font Awesome "wine-bottle" icon unicode character. /// @@ -12453,28 +9530,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Travel + Hotel" })] WineGlassAlt = 0xF5CE, - /// - /// The Font Awesome "wix" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wix" })] - Wix = 0xF5CF, - - /// - /// The Font Awesome "wizards-of-the-coast" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wizards of the coast", "dungeons & dragons", "d&d", "dnd", "fantasy", "game", "gaming", "tabletop" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - WizardsOfTheCoast = 0xF730, - - /// - /// The Font Awesome "wolf-pack-battalion" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wolf pack battalion" })] - WolfPackBattalion = 0xF514, - /// /// The Font Awesome "won-sign" icon unicode character. /// @@ -12482,20 +9537,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Money" })] WonSign = 0xF159, - /// - /// The Font Awesome "wordpress" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wordpress" })] - Wordpress = 0xF19A, - - /// - /// The Font Awesome "wordpress-simple" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wordpress simple" })] - WordpressSimple = 0xF411, - /// /// The Font Awesome "worm" icon unicode character. /// @@ -12503,34 +9544,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Animals", "Disaster + Crisis", "Humanitarian", "Nature" })] Worm = 0xE599, - /// - /// The Font Awesome "wpbeginner" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wpbeginner" })] - Wpbeginner = 0xF297, - - /// - /// The Font Awesome "wpexplorer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wpexplorer" })] - Wpexplorer = 0xF2DE, - - /// - /// The Font Awesome "wpforms" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wpforms" })] - Wpforms = 0xF298, - - /// - /// The Font Awesome "wpressr" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "wpressr", "rendact" })] - Wpressr = 0xF3E4, - /// /// The Font Awesome "wrench" icon unicode character. /// @@ -12538,28 +9551,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Construction", "Maps" })] Wrench = 0xF0AD, - /// - /// The Font Awesome "xbox" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "xbox" })] - [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] - Xbox = 0xF412, - - /// - /// The Font Awesome "xing" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "xing" })] - Xing = 0xF168, - - /// - /// The Font Awesome "square-xing" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square xing" })] - XingSquare = 0xF169, - /// /// The Font Awesome "xmarks-lines" icon unicode character. /// @@ -12574,55 +9565,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] XRay = 0xF497, - /// - /// The Font Awesome "yahoo" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yahoo" })] - Yahoo = 0xF19E, - - /// - /// The Font Awesome "yammer" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yammer" })] - Yammer = 0xF840, - - /// - /// The Font Awesome "yandex" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yandex" })] - Yandex = 0xF413, - - /// - /// The Font Awesome "yandex-international" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yandex international" })] - YandexInternational = 0xF414, - - /// - /// The Font Awesome "yarn" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yarn" })] - Yarn = 0xF7E3, - - /// - /// The Font Awesome "y-combinator" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "y combinator" })] - YCombinator = 0xF23B, - - /// - /// The Font Awesome "yelp" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yelp" })] - Yelp = 0xF1E9, - /// /// The Font Awesome "yen-sign" icon unicode character. /// @@ -12637,33 +9579,4 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Religion", "Spinners" })] YinYang = 0xF6AD, - /// - /// The Font Awesome "yoast" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "yoast" })] - Yoast = 0xF2B1, - - /// - /// The Font Awesome "youtube" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "youtube", "film", "video", "youtube-play", "youtube-square" })] - [FontAwesomeCategoriesAttribute(new[] { "Film + Video" })] - Youtube = 0xF167, - - /// - /// The Font Awesome "square-youtube" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "square youtube" })] - YoutubeSquare = 0xF431, - - /// - /// The Font Awesome "zhihu" icon unicode character. - /// - [Obsolete] - [FontAwesomeSearchTerms(new[] { "zhihu" })] - Zhihu = 0xF63F, - } From 538976667f4f976ac8422d6f886c3a2d510f5d81 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 24 Jun 2023 17:10:47 -0700 Subject: [PATCH 009/120] Add IKeyState (v9) (#1267) --- Dalamud/Game/ClientState/Keys/KeyState.cs | 61 ++++++------------ Dalamud/Plugin/Services/IKeyState.cs | 77 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 41 deletions(-) create mode 100644 Dalamud/Plugin/Services/IKeyState.cs diff --git a/Dalamud/Game/ClientState/Keys/KeyState.cs b/Dalamud/Game/ClientState/Keys/KeyState.cs index 685973e17..ba5cd06d9 100644 --- a/Dalamud/Game/ClientState/Keys/KeyState.cs +++ b/Dalamud/Game/ClientState/Keys/KeyState.cs @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using Serilog; namespace Dalamud.Game.ClientState.Keys; @@ -23,7 +25,10 @@ namespace Dalamud.Game.ClientState.Keys; [PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public class KeyState : IServiceType +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +public class KeyState : IServiceType, IKeyState { // 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 @@ -31,7 +36,7 @@ public class KeyState : IServiceType private const int MaxKeyCode = 0xF0; private readonly IntPtr bufferBase; private readonly IntPtr indexBase; - private VirtualKey[] validVirtualKeyCache = null; + private VirtualKey[]? validVirtualKeyCache; [ServiceManager.ServiceConstructor] private KeyState(SigScanner sigScanner, ClientState clientState) @@ -44,46 +49,29 @@ public class KeyState : IServiceType Log.Verbose($"Keyboard state buffer address 0x{this.bufferBase.ToInt64():X}"); } - /// - /// Get or set the key-pressed state for a given vkCode. - /// - /// The virtual key to change. - /// Whether the specified key is currently pressed. - /// If the vkCode is not valid. Refer to or . - /// If the set value is non-zero. - public unsafe bool this[int vkCode] + /// + public bool this[int vkCode] { get => this.GetRawValue(vkCode) != 0; set => this.SetRawValue(vkCode, value ? 1 : 0); } - /// + /// public bool this[VirtualKey vkCode] { get => this[(int)vkCode]; set => this[(int)vkCode] = value; } - /// - /// Gets the value in the index array. - /// - /// The virtual key to change. - /// The raw value stored in the index array. - /// If the vkCode is not valid. Refer to or . + /// public int GetRawValue(int vkCode) => this.GetRefValue(vkCode); - /// + /// public int GetRawValue(VirtualKey vkCode) => this.GetRawValue((int)vkCode); - /// - /// Sets the value in the index array. - /// - /// The virtual key to change. - /// The raw value to set in the index array. - /// If the vkCode is not valid. Refer to or . - /// If the set value is non-zero. + /// public void SetRawValue(int vkCode, int value) { if (value != 0) @@ -92,32 +80,23 @@ public class KeyState : IServiceType this.GetRefValue(vkCode) = value; } - /// + /// public void SetRawValue(VirtualKey vkCode, int value) => this.SetRawValue((int)vkCode, value); - /// - /// Gets a value indicating whether the given VirtualKey code is regarded as valid input by the game. - /// - /// Virtual key code. - /// If the code is valid. + /// public bool IsVirtualKeyValid(int vkCode) => this.ConvertVirtualKey(vkCode) != 0; - /// + /// public bool IsVirtualKeyValid(VirtualKey vkCode) => this.IsVirtualKeyValid((int)vkCode); - /// - /// Gets an array of virtual keys the game considers valid input. - /// - /// An array of valid virtual keys. - public VirtualKey[] GetValidVirtualKeys() - => this.validVirtualKeyCache ??= Enum.GetValues().Where(vk => this.IsVirtualKeyValid(vk)).ToArray(); + /// + public IEnumerable GetValidVirtualKeys() + => this.validVirtualKeyCache ??= Enum.GetValues().Where(this.IsVirtualKeyValid).ToArray(); - /// - /// Clears the pressed state for all keys. - /// + /// public void ClearAll() { foreach (var vk in this.GetValidVirtualKeys()) diff --git a/Dalamud/Plugin/Services/IKeyState.cs b/Dalamud/Plugin/Services/IKeyState.cs new file mode 100644 index 000000000..c2bca7347 --- /dev/null +++ b/Dalamud/Plugin/Services/IKeyState.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using Dalamud.Game.ClientState.Keys; +using PInvoke; + +namespace Dalamud.Plugin.Services; + +/// +/// Wrapper around the game keystate buffer, which contains the pressed state for all keyboard keys, indexed by virtual vkCode. +/// +/// +/// The stored key state is actually a combination field, however the below ephemeral states are consumed each frame. Setting +/// the value may be mildly useful, however retrieving the value is largely pointless. In testing, it wasn't possible without +/// setting the statue manually. +/// index & 0 = key pressed. +/// index & 1 = key down (ephemeral). +/// index & 2 = key up (ephemeral). +/// index & 3 = short key press (ephemeral). +/// +public interface IKeyState +{ + /// + /// Get or set the key-pressed state for a given vkCode. + /// + /// The virtual key to change. + /// Whether the specified key is currently pressed. + /// If the vkCode is not valid. Refer to or . + /// If the set value is non-zero. + public bool this[int vkCode] { get; set; } + + /// + public bool this[VirtualKey vkCode] { get; set; } + + /// + /// Gets the value in the index array. + /// + /// The virtual key to change. + /// The raw value stored in the index array. + /// If the vkCode is not valid. Refer to or . + public int GetRawValue(int vkCode); + + /// + public int GetRawValue(VirtualKey vkCode); + + /// + /// Sets the value in the index array. + /// + /// The virtual key to change. + /// The raw value to set in the index array. + /// If the vkCode is not valid. Refer to or . + /// If the set value is non-zero. + public void SetRawValue(int vkCode, int value); + + /// + public void SetRawValue(VirtualKey vkCode, int value); + + /// + /// Gets a value indicating whether the given VirtualKey code is regarded as valid input by the game. + /// + /// Virtual key code. + /// If the code is valid. + public bool IsVirtualKeyValid(int vkCode); + + /// + public bool IsVirtualKeyValid(VirtualKey vkCode); + + /// + /// Gets an array of virtual keys the game considers valid input. + /// + /// An array of valid virtual keys. + public IEnumerable GetValidVirtualKeys(); + + /// + /// Clears the pressed state for all keys. + /// + public void ClearAll(); +} From 2677964fc547d3ef1198ea58561ed29a4b3a9f52 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 24 Jun 2023 17:24:54 -0700 Subject: [PATCH 010/120] Add ICondition (v9) (#1262) --- .../Game/ClientState/Conditions/Condition.cs | 62 ++++++++++--------- Dalamud/Plugin/Services/ICondition.cs | 54 ++++++++++++++++ 2 files changed, 87 insertions(+), 29 deletions(-) create mode 100644 Dalamud/Plugin/Services/ICondition.cs diff --git a/Dalamud/Game/ClientState/Conditions/Condition.cs b/Dalamud/Game/ClientState/Conditions/Condition.cs index f611a01c6..b72c91c74 100644 --- a/Dalamud/Game/ClientState/Conditions/Condition.cs +++ b/Dalamud/Game/ClientState/Conditions/Condition.cs @@ -2,6 +2,7 @@ using System; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using Serilog; namespace Dalamud.Game.ClientState.Conditions; @@ -12,13 +13,16 @@ namespace Dalamud.Game.ClientState.Conditions; [PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed partial class Condition : IServiceType +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +public sealed partial class Condition : IServiceType, ICondition { /// - /// The current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has. + /// Gets the current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has. /// - public const int MaxConditionEntries = 104; - + internal const int MaxConditionEntries = 104; + private readonly bool[] cache = new bool[MaxConditionEntries]; [ServiceManager.ServiceConstructor] @@ -27,29 +31,17 @@ public sealed partial class Condition : IServiceType var resolver = clientState.AddressResolver; this.Address = resolver.ConditionFlags; } + + /// + public event ICondition.ConditionChangeDelegate? ConditionChange; - /// - /// A delegate type used with the event. - /// - /// The changed condition. - /// The value the condition is set to. - public delegate void ConditionChangeDelegate(ConditionFlag flag, bool value); + /// + public int MaxEntries => MaxConditionEntries; - /// - /// Event that gets fired when a condition is set. - /// Should only get fired for actual changes, so the previous value will always be !value. - /// - public event ConditionChangeDelegate? ConditionChange; - - /// - /// Gets the condition array base pointer. - /// + /// public IntPtr Address { get; private set; } - /// - /// Check the value of a specific condition/state flag. - /// - /// The condition flag to check. + /// public unsafe bool this[int flag] { get @@ -61,14 +53,11 @@ public sealed partial class Condition : IServiceType } } - /// - public unsafe bool this[ConditionFlag flag] + /// + public bool this[ConditionFlag flag] => this[(int)flag]; - /// - /// Check if any condition flags are set. - /// - /// Whether any single flag is set. + /// public bool Any() { for (var i = 0; i < MaxConditionEntries; i++) @@ -81,6 +70,21 @@ public sealed partial class Condition : IServiceType return false; } + + /// + public bool Any(params ConditionFlag[] flags) + { + foreach (var flag in flags) + { + // this[i] performs range checking, so no need to check here + if (this[flag]) + { + return true; + } + } + + return false; + } [ServiceManager.CallWhenServicesReady] private void ContinueConstruction(Framework framework) diff --git a/Dalamud/Plugin/Services/ICondition.cs b/Dalamud/Plugin/Services/ICondition.cs new file mode 100644 index 000000000..9700cef5a --- /dev/null +++ b/Dalamud/Plugin/Services/ICondition.cs @@ -0,0 +1,54 @@ +using Dalamud.Game.ClientState.Conditions; + +namespace Dalamud.Plugin.Services; + +/// +/// Provides access to conditions (generally player state). You can check whether a player is in combat, mounted, etc. +/// +public interface ICondition +{ + /// + /// A delegate type used with the event. + /// + /// The changed condition. + /// The value the condition is set to. + public delegate void ConditionChangeDelegate(ConditionFlag flag, bool value); + + /// + /// Event that gets fired when a condition is set. + /// Should only get fired for actual changes, so the previous value will always be !value. + /// + public event ConditionChangeDelegate? ConditionChange; + + /// + /// Gets the current max number of conditions. + /// + public int MaxEntries { get; } + + /// + /// Gets the condition array base pointer. + /// + public nint Address { get; } + + /// + /// Check the value of a specific condition/state flag. + /// + /// The condition flag to check. + public bool this[int flag] { get; } + + /// + public bool this[ConditionFlag flag] => this[(int)flag]; + + /// + /// Check if any condition flags are set. + /// + /// Whether any single flag is set. + public bool Any(); + + /// + /// Check if any provided condition flags are set. + /// + /// Whether any single provided flag is set. + /// The condition flags to check. + public bool Any(params ConditionFlag[] flags); +} From a3787498c9e8e48414c7af684bc2664018436040 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 24 Jun 2023 23:38:28 -0700 Subject: [PATCH 011/120] Add IGameNetwork (#1284) Co-authored-by: goat <16760685+goaaats@users.noreply.github.com> --- Dalamud/Game/Network/GameNetwork.cs | 18 ++++++----------- Dalamud/Plugin/Services/IGameNetwork.cs | 26 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 Dalamud/Plugin/Services/IGameNetwork.cs diff --git a/Dalamud/Game/Network/GameNetwork.cs b/Dalamud/Game/Network/GameNetwork.cs index d1fc0bfba..2b6630c8b 100644 --- a/Dalamud/Game/Network/GameNetwork.cs +++ b/Dalamud/Game/Network/GameNetwork.cs @@ -5,6 +5,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using Dalamud.Utility; using Serilog; @@ -16,7 +17,10 @@ namespace Dalamud.Game.Network; [PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed class GameNetwork : IDisposable, IServiceType +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork { private readonly GameNetworkAddressResolver address; private readonly Hook processZonePacketDownHook; @@ -47,16 +51,6 @@ public sealed class GameNetwork : IDisposable, IServiceType this.processZonePacketUpHook = Hook.FromAddress(this.address.ProcessZonePacketUp, this.ProcessZonePacketUpDetour); } - /// - /// The delegate type of a network message event. - /// - /// The pointer to the raw data. - /// The operation ID code. - /// The source actor ID. - /// The taret actor ID. - /// The direction of the packed. - public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction); - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate void ProcessZonePacketDownDelegate(IntPtr a, uint targetId, IntPtr dataPtr); @@ -66,7 +60,7 @@ public sealed class GameNetwork : IDisposable, IServiceType /// /// Event that is called when a network message is sent/received. /// - public event OnNetworkMessageDelegate NetworkMessage; + public event IGameNetwork.OnNetworkMessageDelegate NetworkMessage; /// /// Dispose of managed and unmanaged resources. diff --git a/Dalamud/Plugin/Services/IGameNetwork.cs b/Dalamud/Plugin/Services/IGameNetwork.cs new file mode 100644 index 000000000..eed79b4af --- /dev/null +++ b/Dalamud/Plugin/Services/IGameNetwork.cs @@ -0,0 +1,26 @@ +using Dalamud.Game.Network; + +namespace Dalamud.Plugin.Services; + +/// +/// This class handles interacting with game network events. +/// +public interface IGameNetwork +{ + // TODO(v9): we shouldn't be passing pointers to the actual data here + + /// + /// The delegate type of a network message event. + /// + /// The pointer to the raw data. + /// The operation ID code. + /// The source actor ID. + /// The taret actor ID. + /// The direction of the packed. + public delegate void OnNetworkMessageDelegate(nint dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction); + + /// + /// Event that is called when a network message is sent/received. + /// + public event OnNetworkMessageDelegate NetworkMessage; +} From c991e1f1d3e9a6310a665f598c908e5fb5cf26f1 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sat, 29 Jul 2023 21:09:07 +0200 Subject: [PATCH 012/120] refactor: make IsDataReady internal --- Dalamud/Data/DataManager.cs | 8 +++++--- Dalamud/Plugin/Services/IDataManager.cs | 5 ----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index 407a1b0da..791ba2158 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -131,6 +131,11 @@ public sealed class DataManager : IDisposable, IServiceType, IDataManager } } + /// + /// Gets a value indicating whether Game Data is ready to be read. + /// + internal bool IsDataReady { get; private set; } + /// public ClientLanguage Language { get; private set; } @@ -147,9 +152,6 @@ public sealed class DataManager : IDisposable, IServiceType, IDataManager /// public ExcelModule Excel => this.GameData.Excel; - /// - public bool IsDataReady { get; private set; } - /// public bool HasModifiedGameDataFiles { get; private set; } diff --git a/Dalamud/Plugin/Services/IDataManager.cs b/Dalamud/Plugin/Services/IDataManager.cs index fa8c5bf43..4eac646ad 100644 --- a/Dalamud/Plugin/Services/IDataManager.cs +++ b/Dalamud/Plugin/Services/IDataManager.cs @@ -38,11 +38,6 @@ public interface IDataManager /// public ExcelModule Excel { get; } - /// - /// Gets a value indicating whether Game Data is ready to be read. - /// - public bool IsDataReady { get; } - /// /// Gets a value indicating whether the game data files have been modified by another third-party tool. /// From 0f30b8240c2cd3ba80e83c66b4b30180674c81e1 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 18:40:00 +0200 Subject: [PATCH 013/120] feat: append payloads to SeStringBuilder --- Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs index 36bb10a2d..1e3449618 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs @@ -1,3 +1,6 @@ +using System.Collections.Generic; +using System.Linq; + using Dalamud.Game.Text.SeStringHandling.Payloads; namespace Dalamud.Game.Text.SeStringHandling; @@ -30,6 +33,13 @@ public class SeStringBuilder /// The current builder. public SeStringBuilder Append(string text) => this.AddText(text); + /// + /// Append payloads to the builder. + /// + /// A list of payloads. + /// The current builder. + public SeStringBuilder Append(IEnumerable payloads) => this.Append(new SeString(payloads.ToList())); + /// /// Append raw text to the builder. /// From 982755c4a2858e9abbf662e0789884acfa050a8e Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 18:42:56 +0200 Subject: [PATCH 014/120] fix: reset colors in SeString.CreateItemLink --- Dalamud/Game/Text/SeStringHandling/SeString.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index 6d0c8b0fb..e0cb67cff 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -211,8 +211,8 @@ public class SeString // arrow goes here new TextPayload(displayName), RawPayload.LinkTerminator, - // sometimes there is another set of uiglow/foreground off payloads here - // might be necessary when including additional text after the item name + UIGlowPayload.UIGlowOff, + UIForegroundPayload.UIForegroundOff, }); payloads.InsertRange(3, TextArrowPayloads); From 3f78df23e3a96f2118ac0801c2748c2641135f49 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 18:44:45 +0200 Subject: [PATCH 015/120] feat: item rarity color in SeString.CreateItemLink --- .../Game/Text/SeStringHandling/SeString.cs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index e0cb67cff..c06cdc6b0 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -171,6 +171,7 @@ public class SeString var data = Service.Get(); var displayName = displayNameOverride; + var rarity = 1; // default: white if (displayName == null) { switch (kind) @@ -178,7 +179,9 @@ public class SeString case ItemPayload.ItemKind.Normal: case ItemPayload.ItemKind.Collectible: case ItemPayload.ItemKind.Hq: - displayName = data.GetExcelSheet()?.GetRow(itemId)?.Name; + var item = data.GetExcelSheet()?.GetRow(itemId); + displayName = item?.Name; + rarity = item.Rarity; break; case ItemPayload.ItemKind.EventItem: displayName = data.GetExcelSheet()?.GetRow(itemId)?.Name; @@ -202,21 +205,19 @@ public class SeString displayName += $" {(char)SeIconChar.Collectible}"; } - // TODO: probably a cleaner way to build these than doing the bulk+insert - var payloads = new List(new Payload[] - { - new UIForegroundPayload(0x0225), - new UIGlowPayload(0x0226), - new ItemPayload(itemId, kind), - // arrow goes here - new TextPayload(displayName), - RawPayload.LinkTerminator, - UIGlowPayload.UIGlowOff, - UIForegroundPayload.UIForegroundOff, - }); - payloads.InsertRange(3, TextArrowPayloads); + var textColor = (ushort)(549 + ((rarity - 1) * 2)); + var textGlowColor = (ushort)(textColor + 1); - return new SeString(payloads); + return new SeStringBuilder() + .Add(new ItemPayload(itemId, kind)) + .Append(TextArrowPayloads) + .AddUiForeground(textColor) + .AddUiGlow(textGlowColor) + .AddText(displayName) + .AddUiGlowOff() + .AddUiForegroundOff() + .Add(RawPayload.LinkTerminator) + .Build(); } /// From 08100ef572c46d148e5bd60f43fbaf2f0a531f89 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 18:57:00 +0200 Subject: [PATCH 016/120] fix: add a full item link to SeStringBuilder This changes the behaviour of `AddItemLink` functions. Previously it just added an `ItemPayload`. Now, it adds a full item link, as one would expect. --- Dalamud/Game/Text/SeStringHandling/SeString.cs | 1 + Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index c06cdc6b0..d7d1784f4 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -208,6 +208,7 @@ public class SeString var textColor = (ushort)(549 + ((rarity - 1) * 2)); var textGlowColor = (ushort)(textColor + 1); + // Note: `SeStringBuilder.AddItemLink` uses this function, so don't call it here! return new SeStringBuilder() .Add(new ItemPayload(itemId, kind)) .Append(TextArrowPayloads) diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs index 1e3449618..5b6a83f61 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs @@ -114,7 +114,7 @@ public class SeStringBuilder /// Override for the item's name. /// The current builder. public SeStringBuilder AddItemLink(uint itemId, bool isHq, string? itemNameOverride = null) => - this.Add(new ItemPayload(itemId, isHq, itemNameOverride)); + this.Append(SeString.CreateItemLink(itemId, isHq, itemNameOverride)); /// /// Add an item link to the builder. @@ -124,7 +124,7 @@ public class SeStringBuilder /// Override for the item's name. /// The current builder. public SeStringBuilder AddItemLink(uint itemId, ItemPayload.ItemKind kind, string? itemNameOverride = null) => - this.Add(new ItemPayload(itemId, kind, itemNameOverride)); + this.Append(SeString.CreateItemLink(itemId, kind, itemNameOverride)); /// /// Add an item link to the builder. From e47bfc7acaca9d6a2b4f0f6d7038f7520237ec8a Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 18:58:07 +0200 Subject: [PATCH 017/120] docs: reminder to add a LinkTerminator --- Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs index 5b6a83f61..5d7bcce1d 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs @@ -131,6 +131,7 @@ public class SeStringBuilder /// /// The raw item ID. /// The current builder. + /// To terminate this item link, add a . public SeStringBuilder AddItemLinkRaw(uint rawItemId) => this.Add(ItemPayload.FromRaw(rawItemId)); From dd845a30f0cfb7dc109846ba9bfcda313028264a Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 20:40:42 +0200 Subject: [PATCH 018/120] fix: correct order of CreateItemLink payloads --- Dalamud/Game/Text/SeStringHandling/SeString.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index d7d1784f4..207f65287 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -210,10 +210,10 @@ public class SeString // Note: `SeStringBuilder.AddItemLink` uses this function, so don't call it here! return new SeStringBuilder() - .Add(new ItemPayload(itemId, kind)) - .Append(TextArrowPayloads) .AddUiForeground(textColor) .AddUiGlow(textGlowColor) + .Add(new ItemPayload(itemId, kind)) + .Append(TextArrowPayloads) .AddText(displayName) .AddUiGlowOff() .AddUiForegroundOff() From d6555007ce16745b538a5f960a3771c497168e14 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 20:56:11 +0200 Subject: [PATCH 019/120] fix: adjust TextArrowPayloads based on language --- .../Game/Text/SeStringHandling/SeString.cs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index 207f65287..12cc94c3d 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -52,14 +52,27 @@ public class SeString /// with the appropriate glow and coloring. /// /// A list of all the payloads required to insert the link marker. - public static IEnumerable TextArrowPayloads => new List(new Payload[] + public static IEnumerable TextArrowPayloads { - new UIForegroundPayload(0x01F4), - new UIGlowPayload(0x01F5), - new TextPayload($"{(char)SeIconChar.LinkMarker}"), - UIGlowPayload.UIGlowOff, - UIForegroundPayload.UIForegroundOff, - }); + get + { + var clientState = Service.Get(); + var markerSpace = clientState.ClientLanguage switch + { + ClientLanguage.German => " ", + ClientLanguage.French => " ", + _ => string.Empty, + }; + return new List + { + new UIForegroundPayload(500), + new UIGlowPayload(501), + new TextPayload($"{(char)SeIconChar.LinkMarker}{markerSpace}"), + UIGlowPayload.UIGlowOff, + UIForegroundPayload.UIForegroundOff, + }; + } + } /// /// Gets an empty SeString. From 038de41592cb2e3cd0b43f664fb2289a227cc80d Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 21:38:33 +0200 Subject: [PATCH 020/120] fix: adjust CoordinateString based on language --- .../Game/Text/SeStringHandling/Payloads/MapLinkPayload.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Dalamud/Game/Text/SeStringHandling/Payloads/MapLinkPayload.cs b/Dalamud/Game/Text/SeStringHandling/Payloads/MapLinkPayload.cs index 50945a7ce..667b52e36 100644 --- a/Dalamud/Game/Text/SeStringHandling/Payloads/MapLinkPayload.cs +++ b/Dalamud/Game/Text/SeStringHandling/Payloads/MapLinkPayload.cs @@ -130,7 +130,13 @@ public class MapLinkPayload : Payload var y = Math.Truncate((this.YCoord + fudge) * 10.0f) / 10.0f; // the formatting and spacing the game uses - return $"( {x:0.0} , {y:0.0} )"; + var clientState = Service.Get(); + return clientState.ClientLanguage switch + { + ClientLanguage.German => $"( {x:0.0}, {y:0.0} )", + ClientLanguage.Japanese => $"({x:0.0}, {y:0.0})", + _ => $"( {x:0.0} , {y:0.0} )", + }; } } From 5b6c90f122da0cf3b7bf3f20d103a2752fbf3e3b Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 1 Aug 2023 21:55:51 +0200 Subject: [PATCH 021/120] feat: default ItemKind param for AddItemLink --- Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs index 5d7bcce1d..1fda9f9ae 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs @@ -123,7 +123,7 @@ public class SeStringBuilder /// Kind of item to encode. /// Override for the item's name. /// The current builder. - public SeStringBuilder AddItemLink(uint itemId, ItemPayload.ItemKind kind, string? itemNameOverride = null) => + public SeStringBuilder AddItemLink(uint itemId, ItemPayload.ItemKind kind = ItemPayload.ItemKind.Normal, string? itemNameOverride = null) => this.Append(SeString.CreateItemLink(itemId, kind, itemNameOverride)); /// From a78007b05d92bf0713672ce5dfebc5619b12334d Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Thu, 3 Aug 2023 00:35:43 +0200 Subject: [PATCH 022/120] fix: null check item rarity --- Dalamud/Game/Text/SeStringHandling/SeString.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index 12cc94c3d..2ddb73f12 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -194,7 +194,7 @@ public class SeString case ItemPayload.ItemKind.Hq: var item = data.GetExcelSheet()?.GetRow(itemId); displayName = item?.Name; - rarity = item.Rarity; + rarity = item?.Rarity ?? 1; break; case ItemPayload.ItemKind.EventItem: displayName = data.GetExcelSheet()?.GetRow(itemId)?.Name; From 758ae7c0979ec176a2cc98c6f9cd906d31c723de Mon Sep 17 00:00:00 2001 From: goat Date: Thu, 3 Aug 2023 20:32:31 +0200 Subject: [PATCH 023/120] Remove texture-related IDataManager functions --- Dalamud/Data/DataManager.cs | 155 ------------------ .../Interface/Internal/InterfaceManager.cs | 4 +- Dalamud/Interface/Internal/TextureManager.cs | 24 ++- Dalamud/Plugin/Services/IDataManager.cs | 107 ------------ 4 files changed, 22 insertions(+), 268 deletions(-) diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index 831b25cbc..8c8a2de29 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -36,9 +36,6 @@ namespace Dalamud.Data; #pragma warning restore SA1015 public sealed class DataManager : IDisposable, IServiceType, IDataManager { - private const string IconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}.tex"; - private const string HighResolutionIconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}_hr1.tex"; - private readonly Thread luminaResourceThread; private readonly CancellationTokenSource luminaCancellationTokenSource; @@ -185,158 +182,6 @@ public sealed class DataManager : IDisposable, IServiceType, IDataManager public bool FileExists(string path) => this.GameData.FileExists(path); - /// - /// Get a containing the icon with the given ID. - /// - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(uint iconId) - => this.GetIcon(this.Language, iconId, false); - - /// - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(uint iconId, bool highResolution) - => this.GetIcon(this.Language, iconId, highResolution); - - /// - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(bool isHq, uint iconId) - { - var type = isHq ? "hq/" : string.Empty; - return this.GetIcon(type, iconId); - } - - /// - /// Get a containing the icon with the given ID, of the given language. - /// - /// The requested language. - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(ClientLanguage iconLanguage, uint iconId) - => this.GetIcon(iconLanguage, iconId, false); - - /// - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(ClientLanguage iconLanguage, uint iconId, bool highResolution) - { - var type = iconLanguage switch - { - ClientLanguage.Japanese => "ja/", - ClientLanguage.English => "en/", - ClientLanguage.German => "de/", - ClientLanguage.French => "fr/", - _ => throw new ArgumentOutOfRangeException(nameof(iconLanguage), $"Unknown Language: {iconLanguage}"), - }; - - return this.GetIcon(type, iconId, highResolution); - } - - /// - /// Get a containing the icon with the given ID, of the given type. - /// - /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon). - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(string? type, uint iconId) - => this.GetIcon(type, iconId, false); - - /// - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(string? type, uint iconId, bool highResolution) - { - var format = highResolution ? HighResolutionIconFileFormat : IconFileFormat; - - type ??= string.Empty; - if (type.Length > 0 && !type.EndsWith("/")) - type += "/"; - - var filePath = string.Format(format, iconId / 1000, type, iconId); - var file = this.GetFile(filePath); - - if (type == string.Empty || file != default) - return file; - - // Couldn't get specific type, try for generic version. - filePath = string.Format(format, iconId / 1000, string.Empty, iconId); - file = this.GetFile(filePath); - return file; - } - - /// - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetHqIcon(uint iconId) - => this.GetIcon(true, iconId); - - /// - [Obsolete("Use ITextureProvider instead")] - [return: NotNullIfNotNull(nameof(tex))] - public TextureWrap? GetImGuiTexture(TexFile? tex) - { - if (tex is null) - return null; - - var im = Service.Get(); - var buffer = tex.TextureBuffer; - var bpp = 1 << (((int)tex.Header.Format & (int)TexFile.TextureFormat.BppMask) >> - (int)TexFile.TextureFormat.BppShift); - - var (dxgiFormat, conversion) = TexFile.GetDxgiFormatFromTextureFormat(tex.Header.Format, false); - if (conversion != TexFile.DxgiFormatConversion.NoConversion || !im.SupportsDxgiFormat((Format)dxgiFormat)) - { - dxgiFormat = (int)Format.B8G8R8A8_UNorm; - buffer = buffer.Filter(0, 0, TexFile.TextureFormat.B8G8R8A8); - bpp = 32; - } - - var pitch = buffer is BlockCompressionTextureBuffer - ? Math.Max(1, (buffer.Width + 3) / 4) * 2 * bpp - : ((buffer.Width * bpp) + 7) / 8; - return im.LoadImageFromDxgiFormat(buffer.RawData, pitch, buffer.Width, buffer.Height, (Format)dxgiFormat); - } - - /// - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTexture(string path) - => this.GetImGuiTexture(this.GetFile(path)); - - /// - /// Get a containing the icon with the given ID. - /// - /// The icon ID. - /// The containing the icon. - /// TODO(v9): remove in api9 in favor of GetImGuiTextureIcon(uint iconId, bool highResolution) - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(uint iconId) - => this.GetImGuiTexture(this.GetIcon(iconId, false)); - - /// - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(uint iconId, bool highResolution) - => this.GetImGuiTexture(this.GetIcon(iconId, highResolution)); - - /// - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(bool isHq, uint iconId) - => this.GetImGuiTexture(this.GetIcon(isHq, iconId)); - - /// - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(ClientLanguage iconLanguage, uint iconId) - => this.GetImGuiTexture(this.GetIcon(iconLanguage, iconId)); - - /// - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(string type, uint iconId) - => this.GetImGuiTexture(this.GetIcon(type, iconId)); - - /// - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureHqIcon(uint iconId) - => this.GetImGuiTexture(this.GetHqIcon(iconId)); - #endregion /// diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 841511f55..ad1e514c7 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -325,7 +325,7 @@ internal class InterfaceManager : IDisposable, IServiceType /// The height in pixels. /// Format of the texture. /// A texture, ready to use in ImGui. - public TextureWrap LoadImageFromDxgiFormat(Span data, int pitch, int width, int height, Format dxgiFormat) + public DalamudTextureWrap LoadImageFromDxgiFormat(Span data, int pitch, int width, int height, Format dxgiFormat) { if (this.scene == null) throw new InvalidOperationException("Scene isn't ready."); @@ -360,7 +360,7 @@ internal class InterfaceManager : IDisposable, IServiceType } // no sampler for now because the ImGui implementation we copied doesn't allow for changing it - return new D3DTextureWrap(resView, width, height); + return new DalamudTextureWrap(new D3DTextureWrap(resView, width, height)); } #nullable restore diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 4b2f1f362..de5613eed 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -13,6 +13,8 @@ using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using ImGuiScene; using Lumina.Data.Files; +using Lumina.Data.Parsing.Tex.Buffers; +using SharpDX.DXGI; namespace Dalamud.Interface.Internal; @@ -207,10 +209,24 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP if (!this.im.IsReady) throw new InvalidOperationException("Cannot create textures before scene is ready"); - -#pragma warning disable CS0618 - return this.dataManager.GetImGuiTexture(file) as IDalamudTextureWrap; -#pragma warning restore CS0618 + + var buffer = file.TextureBuffer; + var bpp = 1 << (((int)file.Header.Format & (int)TexFile.TextureFormat.BppMask) >> + (int)TexFile.TextureFormat.BppShift); + + var (dxgiFormat, conversion) = TexFile.GetDxgiFormatFromTextureFormat(file.Header.Format, false); + if (conversion != TexFile.DxgiFormatConversion.NoConversion || !im.SupportsDxgiFormat((Format)dxgiFormat)) + { + dxgiFormat = (int)Format.B8G8R8A8_UNorm; + buffer = buffer.Filter(0, 0, TexFile.TextureFormat.B8G8R8A8); + bpp = 32; + } + + var pitch = buffer is BlockCompressionTextureBuffer + ? Math.Max(1, (buffer.Width + 3) / 4) * 2 * bpp + : ((buffer.Width * bpp) + 7) / 8; + + return this.im.LoadImageFromDxgiFormat(buffer.RawData, pitch, buffer.Width, buffer.Height, (Format)dxgiFormat); } /// diff --git a/Dalamud/Plugin/Services/IDataManager.cs b/Dalamud/Plugin/Services/IDataManager.cs index a47303ea6..3ae10b0c7 100644 --- a/Dalamud/Plugin/Services/IDataManager.cs +++ b/Dalamud/Plugin/Services/IDataManager.cs @@ -81,111 +81,4 @@ public interface IDataManager /// The path inside of the game files. /// True if the file exists. public bool FileExists(string path); - - /// - /// Get a containing the icon with the given ID. - /// - /// The icon ID. - /// Return high resolution version. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(uint iconId, bool highResolution = false); - - /// - /// Get a containing the icon with the given ID, of the given language. - /// - /// The requested language. - /// The icon ID. - /// Return high resolution version. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(ClientLanguage iconLanguage, uint iconId, bool highResolution = false); - - /// - /// Get a containing the icon with the given ID, of the given type. - /// - /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon). - /// The icon ID. - /// Return high resolution version. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(string? type, uint iconId, bool highResolution = false); - - /// - /// Get a containing the icon with the given ID. - /// - /// The icon ID. - /// Return the high resolution version. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(uint iconId, bool highResolution = false); - - /// - /// Get a containing the icon with the given ID, of the given quality. - /// - /// A value indicating whether the icon should be HQ. - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetIcon(bool isHq, uint iconId); - - /// - /// Get a containing the HQ icon with the given ID. - /// - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TexFile? GetHqIcon(uint iconId); - - /// - /// Get the passed as a drawable ImGui TextureWrap. - /// - /// The Lumina . - /// A that can be used to draw the texture. - [Obsolete("Use ITextureProvider instead")] - [return: NotNullIfNotNull(nameof(tex))] - public TextureWrap? GetImGuiTexture(TexFile? tex); - - /// - /// Get the passed texture path as a drawable ImGui TextureWrap. - /// - /// The internal path to the texture. - /// A that can be used to draw the texture. - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTexture(string path); - - /// - /// Get a containing the icon with the given ID, of the given quality. - /// - /// A value indicating whether the icon should be HQ. - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(bool isHq, uint iconId); - - /// - /// Get a containing the icon with the given ID, of the given language. - /// - /// The requested language. - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(ClientLanguage iconLanguage, uint iconId); - - /// - /// Get a containing the icon with the given ID, of the given type. - /// - /// The type of the icon (e.g. 'hq' to get the HQ variant of an item icon). - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureIcon(string type, uint iconId); - - /// - /// Get a containing the HQ icon with the given ID. - /// - /// The icon ID. - /// The containing the icon. - [Obsolete("Use ITextureProvider instead")] - public TextureWrap? GetImGuiTextureHqIcon(uint iconId); } From 02e1f2502e5031e5c2897c04d931643014c99390 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 4 Aug 2023 19:36:09 +0200 Subject: [PATCH 024/120] refactor: move Dalamud.Interface utils into main assembly, warnings pass --- .editorconfig | 2 +- Dalamud.Interface/Dalamud.Interface.csproj | 17 ---- Dalamud.Interface/ImGuiTable.cs | 41 --------- Dalamud.Interface/InterfaceHelpers.cs | 6 -- Dalamud.sln | 14 --- Dalamud/Dalamud.csproj | 1 - Dalamud/Data/DataManager.cs | 18 ++-- Dalamud/Game/Config/GameConfig.cs | 3 +- Dalamud/Game/Config/GameConfigSection.cs | 13 ++- Dalamud/Game/Gui/GameGui.cs | 1 + Dalamud/GlobalSuppressions.cs | 19 ++++ Dalamud/GlobalUsings.cs | 1 + .../ImGuiComponents.ColorPickerWithPalette.cs | 1 + Dalamud/Interface/DragDrop/DragDropInterop.cs | 4 +- Dalamud/Interface/DragDrop/DragDropManager.cs | 2 + Dalamud/Interface/DragDrop/DragDropTarget.cs | 6 +- .../Interface/DragDrop/IDragDropManager.cs | 13 ++- .../Interface/GameFonts/GameFontManager.cs | 3 +- .../ImGuiFileDialog/FileDialog.UI.cs | 1 + .../Interface/Internal/DalamudInterface.cs | 3 +- .../Interface/Internal/InterfaceManager.cs | 1 + .../Notifications/NotificationManager.cs | 1 + Dalamud/Interface/Internal/TextureManager.cs | 2 +- Dalamud/Interface/Internal/UiDebug.cs | 1 + .../Internal/Windows/BranchSwitcherWindow.cs | 1 + .../Internal/Windows/ChangelogWindow.cs | 1 + .../Internal/Windows/ComponentDemoWindow.cs | 1 + .../Internal/Windows/ConsoleWindow.cs | 1 + .../Internal/Windows/Data/DataWindow.cs | 1 + .../Windows/Data/Widgets/DataShareWidget.cs | 3 +- .../Data/Widgets/FontAwesomeTestWidget.cs | 4 +- .../Data/Widgets/NetworkMonitorWidget.cs | 3 +- .../Windows/Data/Widgets/TargetWidget.cs | 1 + .../Data/Widgets/TaskSchedulerWidget.cs | 1 + .../Windows/Data/Widgets/TexWidget.cs | 4 +- .../Windows/Data/Widgets/ToastWidget.cs | 1 + .../Windows/GamepadModeNotifierWindow.cs | 1 + .../PluginInstaller/PluginInstallerWindow.cs | 3 +- .../PluginInstaller/ProfileManagerWidget.cs | 3 +- .../Internal/Windows/ProfilerWindow.cs | 1 + .../Windows/SelfTest/SelfTestWindow.cs | 1 + .../Internal/Windows/Settings/SettingsTab.cs | 5 +- .../Windows/Settings/SettingsWindow.cs | 3 +- .../Windows/Settings/Tabs/SettingsTabAbout.cs | 3 +- .../Windows/Settings/Tabs/SettingsTabDtr.cs | 1 + .../Settings/Tabs/SettingsTabExperimental.cs | 1 + .../Windows/Settings/Tabs/SettingsTabLook.cs | 1 + .../Settings/Widgets/ButtonSettingsEntry.cs | 1 + .../Widgets/DevPluginsSettingsEntry.cs | 3 +- .../Settings/Widgets/GapSettingsEntry.cs | 1 + .../Settings/Widgets/HintSettingsEntry.cs | 1 + .../Widgets/LanguageChooserSettingsEntry.cs | 1 + .../Settings/Widgets/SettingsEntry{T}.cs | 3 +- .../Widgets/ThirdRepoSettingsEntry.cs | 3 +- .../Windows/StyleEditor/StyleEditorWindow.cs | 1 + .../Internal/Windows/TitleScreenMenuWindow.cs | 3 +- .../Interface/Utility}/ImGuiClip.cs | 8 +- .../{ => Utility}/ImGuiExtensions.cs | 3 +- .../Interface/{ => Utility}/ImGuiHelpers.cs | 6 +- Dalamud/Interface/Utility/ImGuiTable.cs | 56 ++++++++++++ .../Interface/Utility}/Raii/Color.cs | 17 ++-- .../Interface/Utility}/Raii/EndObjects.cs | 42 +++++---- .../Interface/Utility}/Raii/Font.cs | 14 +-- .../Interface/Utility}/Raii/Id.cs | 16 ++-- .../Interface/Utility}/Raii/Indent.cs | 6 +- .../Interface/Utility}/Raii/Style.cs | 19 ++-- .../Interface/Utility}/Table/Column.cs | 5 +- .../Interface/Utility}/Table/ColumnFlags.cs | 13 +-- .../Interface/Utility}/Table/ColumnSelect.cs | 22 ++--- .../Interface/Utility}/Table/ColumnString.cs | 17 ++-- .../Interface/Utility}/Table/Table.cs | 88 ++++++++++--------- Dalamud/Interface/Windowing/Window.cs | 2 + Dalamud/Plugin/Internal/PluginManager.cs | 17 ++-- Dalamud/Plugin/Services/IGameConfig.cs | 6 +- Dalamud/Plugin/Services/IKeyState.cs | 5 +- .../Utility}/ArrayExtensions.cs | 9 +- Dalamud/Utility/FuzzyMatcher.cs | 68 ++++++++------ .../Utility}/StableInsertionSortExtension.cs | 20 ++++- Dalamud/Utility/Util.cs | 1 + targets/Dalamud.Plugin.targets | 1 - 80 files changed, 394 insertions(+), 303 deletions(-) delete mode 100644 Dalamud.Interface/Dalamud.Interface.csproj delete mode 100644 Dalamud.Interface/ImGuiTable.cs delete mode 100644 Dalamud.Interface/InterfaceHelpers.cs create mode 100644 Dalamud/GlobalUsings.cs rename {Dalamud.Interface => Dalamud/Interface/Utility}/ImGuiClip.cs (97%) rename Dalamud/Interface/{ => Utility}/ImGuiExtensions.cs (98%) rename Dalamud/Interface/{ => Utility}/ImGuiHelpers.cs (99%) create mode 100644 Dalamud/Interface/Utility/ImGuiTable.cs rename {Dalamud.Interface => Dalamud/Interface/Utility}/Raii/Color.cs (83%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Raii/EndObjects.cs (94%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Raii/Font.cs (81%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Raii/Id.cs (82%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Raii/Indent.cs (91%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Raii/Style.cs (95%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Table/Column.cs (92%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Table/ColumnFlags.cs (89%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Table/ColumnSelect.cs (66%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Table/ColumnString.cs (75%) rename {Dalamud.Interface => Dalamud/Interface/Utility}/Table/Table.cs (64%) rename {Dalamud.Interface => Dalamud/Utility}/ArrayExtensions.cs (80%) rename {Dalamud.Interface => Dalamud/Utility}/StableInsertionSortExtension.cs (57%) diff --git a/.editorconfig b/.editorconfig index 829de8f05..0e4f800e0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -35,7 +35,7 @@ dotnet_naming_rule.private_instance_fields_rule.severity = warning dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols dotnet_naming_rule.private_static_fields_rule.severity = warning -dotnet_naming_rule.private_static_fields_rule.style = upper_camel_case_style +dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols dotnet_naming_rule.private_static_readonly_rule.severity = warning dotnet_naming_rule.private_static_readonly_rule.style = upper_camel_case_style diff --git a/Dalamud.Interface/Dalamud.Interface.csproj b/Dalamud.Interface/Dalamud.Interface.csproj deleted file mode 100644 index 1dd8468be..000000000 --- a/Dalamud.Interface/Dalamud.Interface.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - net7.0-windows - x64 - x64;AnyCPU - enable - enable - true - Dalamud.Interface - - - - - - - diff --git a/Dalamud.Interface/ImGuiTable.cs b/Dalamud.Interface/ImGuiTable.cs deleted file mode 100644 index 5ea6a2c9a..000000000 --- a/Dalamud.Interface/ImGuiTable.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Dalamud.Interface.Raii; -using ImGuiNET; - -namespace Dalamud.Interface; - -public static class ImGuiTable -{ - // Draw a simple table with the given data using the drawRow action. - // Headers and thus columns and column count are defined by columnTitles. - public static void DrawTable(string label, IEnumerable data, Action drawRow, ImGuiTableFlags flags = ImGuiTableFlags.None, - params string[] columnTitles) - { - if (columnTitles.Length == 0) - return; - - using var table = ImRaii.Table(label, columnTitles.Length, flags); - if (!table) - return; - - foreach (var title in columnTitles) - { - ImGui.TableNextColumn(); - ImGui.TableHeader(title); - } - - foreach (var datum in data) - { - ImGui.TableNextRow(); - drawRow(datum); - } - } - - // Draw a simple table with the given data using the drawRow action inside a collapsing header. - // Headers and thus columns and column count are defined by columnTitles. - public static void DrawTabbedTable(string label, IEnumerable data, Action drawRow, ImGuiTableFlags flags = ImGuiTableFlags.None, - params string[] columnTitles) - { - if (ImGui.CollapsingHeader(label)) - DrawTable($"{label}##Table", data, drawRow, flags, columnTitles); - } -} diff --git a/Dalamud.Interface/InterfaceHelpers.cs b/Dalamud.Interface/InterfaceHelpers.cs deleted file mode 100644 index 26f09bedb..000000000 --- a/Dalamud.Interface/InterfaceHelpers.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Dalamud.Interface; - -public static class InterfaceHelpers -{ - public static float GlobalScale = 1.0f; -} diff --git a/Dalamud.sln b/Dalamud.sln index 20442e52d..443f38496 100644 --- a/Dalamud.sln +++ b/Dalamud.sln @@ -38,8 +38,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFXIVClientStructs.InteropS EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DalamudCrashHandler", "DalamudCrashHandler\DalamudCrashHandler.vcxproj", "{317A264C-920B-44A1-8A34-F3A6827B0705}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Interface", "Dalamud.Interface\Dalamud.Interface.csproj", "{757C997D-AA58-4241-8299-243C56514917}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -204,18 +202,6 @@ Global {317A264C-920B-44A1-8A34-F3A6827B0705}.Release|x64.Build.0 = Release|x64 {317A264C-920B-44A1-8A34-F3A6827B0705}.Release|x86.ActiveCfg = Release|x64 {317A264C-920B-44A1-8A34-F3A6827B0705}.Release|x86.Build.0 = Release|x64 - {757C997D-AA58-4241-8299-243C56514917}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Debug|Any CPU.Build.0 = Debug|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Debug|x64.ActiveCfg = Debug|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Debug|x64.Build.0 = Debug|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Debug|x86.ActiveCfg = Debug|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Debug|x86.Build.0 = Debug|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Release|Any CPU.ActiveCfg = Release|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Release|Any CPU.Build.0 = Release|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Release|x64.ActiveCfg = Release|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Release|x64.Build.0 = Release|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Release|x86.ActiveCfg = Release|Any CPU - {757C997D-AA58-4241-8299-243C56514917}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 6e6a01fa9..b147dc961 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -87,7 +87,6 @@ - diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index 8c8a2de29..fb167283f 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -1,27 +1,19 @@ -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; -using Dalamud.Interface.Internal; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; -using Dalamud.Utility; using Dalamud.Utility.Timing; -using ImGuiScene; using JetBrains.Annotations; using Lumina; using Lumina.Data; -using Lumina.Data.Files; -using Lumina.Data.Parsing.Tex.Buffers; using Lumina.Excel; using Newtonsoft.Json; using Serilog; -using SharpDX.DXGI; namespace Dalamud.Data; @@ -131,11 +123,6 @@ public sealed class DataManager : IDisposable, IServiceType, IDataManager } } - /// - /// Gets a value indicating whether Game Data is ready to be read. - /// - internal bool IsDataReady { get; private set; } - /// public ClientLanguage Language { get; private set; } @@ -155,6 +142,11 @@ public sealed class DataManager : IDisposable, IServiceType, IDataManager /// public bool HasModifiedGameDataFiles { get; private set; } + /// + /// Gets a value indicating whether Game Data is ready to be read. + /// + internal bool IsDataReady { get; private set; } + #region Lumina Wrappers /// diff --git a/Dalamud/Game/Config/GameConfig.cs b/Dalamud/Game/Config/GameConfig.cs index dfdb8b5d2..49d24c2a5 100644 --- a/Dalamud/Game/Config/GameConfig.cs +++ b/Dalamud/Game/Config/GameConfig.cs @@ -1,5 +1,4 @@ -using System; -using Dalamud.Hooking; +using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; diff --git a/Dalamud/Game/Config/GameConfigSection.cs b/Dalamud/Game/Config/GameConfigSection.cs index 6c87ad3cf..ea79a7fc8 100644 --- a/Dalamud/Game/Config/GameConfigSection.cs +++ b/Dalamud/Game/Config/GameConfigSection.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Diagnostics; using Dalamud.Memory; @@ -18,11 +17,6 @@ public class GameConfigSection private readonly ConcurrentDictionary indexMap = new(); private readonly ConcurrentDictionary enumMap = new(); - /// - /// Event which is fired when a game config option is changed within the section. - /// - public event EventHandler Changed; - /// /// Initializes a new instance of the class. /// @@ -54,6 +48,11 @@ public class GameConfigSection /// Pointer to unmanaged ConfigBase. internal unsafe delegate ConfigBase* GetConfigBaseDelegate(); + /// + /// Event which is fired when a game config option is changed within the section. + /// + public event EventHandler? Changed; + /// /// Gets the number of config entries contained within the section. /// Some entries may be empty with no data. diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 0235bef5a..3954954a3 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Hooking; using Dalamud.Interface; +using Dalamud.Interface.Utility; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; diff --git a/Dalamud/GlobalSuppressions.cs b/Dalamud/GlobalSuppressions.cs index 7426ed5c8..1b869295b 100644 --- a/Dalamud/GlobalSuppressions.cs +++ b/Dalamud/GlobalSuppressions.cs @@ -15,3 +15,22 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1127:Generic type constraints should be on their own line", Justification = "I like this better")] [assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1028:Code should not contain trailing whitespace", Justification = "I don't care anymore")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header", Justification = "We don't do those yet")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:ParametersMustBeOnSameLineOrSeparateLines", Justification = "I don't care anymore")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:ParametersMustBeOnSameLineOrSeparateLines", Justification = "I don't care anymore")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1407:ArithmeticExpressionsMustDeclarePrecedence", Justification = "I don't care anymore")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:SplitParametersMustStartOnLineAfterDeclaration", Justification = "Reviewed.")] + +// ImRAII stuff +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Raii")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:PartialElementsMustBeDocumented", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Raii")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Table")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:PartialElementsMustBeDocumented", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Table")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed.", Scope = "type", Target = "Dalamud.Interface.Utility.ImGuiClip")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:PartialElementsMustBeDocumented", Justification = "Reviewed.", Scope = "type", Target = "Dalamud.Interface.Utility.ImGuiClip")] +[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:CodeMustNotContainMultipleWhitespaceInARow", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Raii")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Table")] +[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Raii")] +[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Table")] +[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Raii")] +[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.", Scope = "namespaceanddescendants", Target = "Dalamud.Interface.Utility.Table")] diff --git a/Dalamud/GlobalUsings.cs b/Dalamud/GlobalUsings.cs new file mode 100644 index 000000000..062a3f981 --- /dev/null +++ b/Dalamud/GlobalUsings.cs @@ -0,0 +1 @@ +global using System; diff --git a/Dalamud/Interface/Components/ImGuiComponents.ColorPickerWithPalette.cs b/Dalamud/Interface/Components/ImGuiComponents.ColorPickerWithPalette.cs index e9db345cb..aa707aecb 100644 --- a/Dalamud/Interface/Components/ImGuiComponents.ColorPickerWithPalette.cs +++ b/Dalamud/Interface/Components/ImGuiComponents.ColorPickerWithPalette.cs @@ -1,5 +1,6 @@ using System.Numerics; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Components; diff --git a/Dalamud/Interface/DragDrop/DragDropInterop.cs b/Dalamud/Interface/DragDrop/DragDropInterop.cs index 28a2644a5..6edd5642e 100644 --- a/Dalamud/Interface/DragDrop/DragDropInterop.cs +++ b/Dalamud/Interface/DragDrop/DragDropInterop.cs @@ -34,9 +34,9 @@ internal partial class DragDropManager internal struct POINTL { [ComAliasName("Microsoft.VisualStudio.OLE.Interop.LONG")] - public int x; + public int X; [ComAliasName("Microsoft.VisualStudio.OLE.Interop.LONG")] - public int y; + public int Y; } private static class DragDropInterop diff --git a/Dalamud/Interface/DragDrop/DragDropManager.cs b/Dalamud/Interface/DragDrop/DragDropManager.cs index 8336edc11..e8641035f 100644 --- a/Dalamud/Interface/DragDrop/DragDropManager.cs +++ b/Dalamud/Interface/DragDrop/DragDropManager.cs @@ -16,7 +16,9 @@ namespace Dalamud.Interface.DragDrop; /// [PluginInterface] [ServiceManager.EarlyLoadedService] +#pragma warning disable SA1015 [ResolveVia] +#pragma warning restore SA1015 internal partial class DragDropManager : IDisposable, IDragDropManager, IServiceType { private nint windowHandlePtr = nint.Zero; diff --git a/Dalamud/Interface/DragDrop/DragDropTarget.cs b/Dalamud/Interface/DragDrop/DragDropTarget.cs index 5e7166fb3..628f1100c 100644 --- a/Dalamud/Interface/DragDrop/DragDropTarget.cs +++ b/Dalamud/Interface/DragDrop/DragDropTarget.cs @@ -51,7 +51,7 @@ internal partial class DragDropManager : DragDropManager.IDropTarget this.Extensions = this.Files.Select(Path.GetExtension).Where(p => !p.IsNullOrEmpty()).Distinct().ToHashSet(); } - Log.Debug("[DragDrop] Entering external Drag and Drop with {KeyState} at {PtX}, {PtY} and with {N} files.", (DragDropInterop.ModifierKeys)grfKeyState, pt.x, pt.y, this.Files.Count + this.Directories.Count); + Log.Debug("[DragDrop] Entering external Drag and Drop with {KeyState} at {PtX}, {PtY} and with {N} files.", (DragDropInterop.ModifierKeys)grfKeyState, pt.X, pt.Y, this.Files.Count + this.Directories.Count); } /// Invoked every windows update-frame as long as the drag and drop process keeps hovering over an FFXIV-related viewport. @@ -67,7 +67,7 @@ internal partial class DragDropManager : DragDropManager.IDropTarget this.lastUpdateFrame = frame; this.lastKeyState = UpdateIo((DragDropInterop.ModifierKeys)grfKeyState, false); pdwEffect &= (uint)DragDropInterop.DropEffects.Copy; - Log.Verbose("[DragDrop] External Drag and Drop with {KeyState} at {PtX}, {PtY}.", (DragDropInterop.ModifierKeys)grfKeyState, pt.x, pt.y); + Log.Verbose("[DragDrop] External Drag and Drop with {KeyState} at {PtX}, {PtY}.", (DragDropInterop.ModifierKeys)grfKeyState, pt.X, pt.Y); } } @@ -101,7 +101,7 @@ internal partial class DragDropManager : DragDropManager.IDropTarget pdwEffect = 0; } - Log.Debug("[DragDrop] Dropping {N} files with {KeyState} at {PtX}, {PtY}.", this.Files.Count + this.Directories.Count, (DragDropInterop.ModifierKeys)grfKeyState, pt.x, pt.y); + Log.Debug("[DragDrop] Dropping {N} files with {KeyState} at {PtX}, {PtY}.", this.Files.Count + this.Directories.Count, (DragDropInterop.ModifierKeys)grfKeyState, pt.X, pt.Y); } private static DragDropInterop.ModifierKeys UpdateIo(DragDropInterop.ModifierKeys keys, bool entering) diff --git a/Dalamud/Interface/DragDrop/IDragDropManager.cs b/Dalamud/Interface/DragDrop/IDragDropManager.cs index 736c8af24..a8a0d63b0 100644 --- a/Dalamud/Interface/DragDrop/IDragDropManager.cs +++ b/Dalamud/Interface/DragDrop/IDragDropManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace Dalamud.Interface.DragDrop; @@ -23,20 +22,20 @@ public interface IDragDropManager /// Gets the list of directories currently being dragged from an external application over any of the games viewports. public IReadOnlyList Directories { get; } - /// Create an ImGui drag & drop source that is active only if anything is being dragged from an external source. - /// The label used for the drag & drop payload. + /// Create an ImGui drag and drop source that is active only if anything is being dragged from an external source. + /// The label used for the drag and drop payload. /// A function returning whether the current status is relevant for this source. Checked before creating the source but only if something is being dragged. public void CreateImGuiSource(string label, Func validityCheck) => this.CreateImGuiSource(label, validityCheck, _ => false); - /// Create an ImGui drag & drop source that is active only if anything is being dragged from an external source. - /// The label used for the drag & drop payload. + /// Create an ImGui drag and drop source that is active only if anything is being dragged from an external source. + /// The label used for the drag and drop payload. /// A function returning whether the current status is relevant for this source. Checked before creating the source but only if something is being dragged. /// Executes ImGui functions to build a tooltip. Should return true if it creates any tooltip and false otherwise. If multiple sources are active, only the first non-empty tooltip type drawn in a frame will be used. public void CreateImGuiSource(string label, Func validityCheck, Func tooltipBuilder); - /// Create an ImGui drag & drop target on the last ImGui object. - /// The label used for the drag & drop payload. + /// Create an ImGui drag and drop target on the last ImGui object. + /// The label used for the drag and drop payload. /// On success, contains the list of file paths dropped onto the target. /// On success, contains the list of directory paths dropped onto the target. /// True if items were dropped onto the target this frame, false otherwise. diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index ad0e47273..d8130f692 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -9,12 +9,13 @@ using System.Threading.Tasks; using Dalamud.Data; using Dalamud.Game; using Dalamud.Interface.Internal; +using Dalamud.Interface.Utility; using Dalamud.Utility.Timing; using ImGuiNET; using Lumina.Data.Files; using Serilog; -using static Dalamud.Interface.ImGuiHelpers; +using static Dalamud.Interface.Utility.ImGuiHelpers; namespace Dalamud.Interface.GameFonts; diff --git a/Dalamud/Interface/ImGuiFileDialog/FileDialog.UI.cs b/Dalamud/Interface/ImGuiFileDialog/FileDialog.UI.cs index d3be8da95..0dd1410d5 100644 --- a/Dalamud/Interface/ImGuiFileDialog/FileDialog.UI.cs +++ b/Dalamud/Interface/ImGuiFileDialog/FileDialog.UI.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Numerics; +using Dalamud.Interface.Utility; using Dalamud.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index 479297c20..a7f7e6209 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -21,8 +21,9 @@ using Dalamud.Interface.Internal.Windows.PluginInstaller; using Dalamud.Interface.Internal.Windows.SelfTest; using Dalamud.Interface.Internal.Windows.Settings; using Dalamud.Interface.Internal.Windows.StyleEditor; -using Dalamud.Interface.Raii; using Dalamud.Interface.Style; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using Dalamud.Logging; using Dalamud.Logging.Internal; diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index ad1e514c7..794b6c6b3 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -19,6 +19,7 @@ using Dalamud.Interface.GameFonts; using Dalamud.Interface.Internal.ManagedAsserts; using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Style; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Utility; using Dalamud.Utility.Timing; diff --git a/Dalamud/Interface/Internal/Notifications/NotificationManager.cs b/Dalamud/Interface/Internal/Notifications/NotificationManager.cs index e941db7a4..9d20d6d3e 100644 --- a/Dalamud/Interface/Internal/Notifications/NotificationManager.cs +++ b/Dalamud/Interface/Internal/Notifications/NotificationManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Numerics; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using Dalamud.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index de5613eed..983ae9963 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -215,7 +215,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP (int)TexFile.TextureFormat.BppShift); var (dxgiFormat, conversion) = TexFile.GetDxgiFormatFromTextureFormat(file.Header.Format, false); - if (conversion != TexFile.DxgiFormatConversion.NoConversion || !im.SupportsDxgiFormat((Format)dxgiFormat)) + if (conversion != TexFile.DxgiFormatConversion.NoConversion || !this.im.SupportsDxgiFormat((Format)dxgiFormat)) { dxgiFormat = (int)Format.B8G8R8A8_UNorm; buffer = buffer.Filter(0, 0, TexFile.TextureFormat.B8G8R8A8); diff --git a/Dalamud/Interface/Internal/UiDebug.cs b/Dalamud/Interface/Internal/UiDebug.cs index d1e7a6b78..b1f27828c 100644 --- a/Dalamud/Interface/Internal/UiDebug.cs +++ b/Dalamud/Interface/Internal/UiDebug.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using Dalamud.Game; using Dalamud.Game.Gui; +using Dalamud.Interface.Utility; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Component.GUI; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs b/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs index b599fb58f..05d8d04e8 100644 --- a/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs +++ b/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Networking.Http; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs index 05854210e..e61cb400b 100644 --- a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs @@ -3,6 +3,7 @@ using System.IO; using System.Numerics; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/ComponentDemoWindow.cs b/Dalamud/Interface/Internal/Windows/ComponentDemoWindow.cs index 638b30e66..8c5458557 100644 --- a/Dalamud/Interface/Internal/Windows/ComponentDemoWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ComponentDemoWindow.cs @@ -6,6 +6,7 @@ using Dalamud.Interface.Animation; using Dalamud.Interface.Animation.EasingFunctions; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs index 872fdcd37..bcbad1a21 100644 --- a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs @@ -10,6 +10,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Game.Command; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Logging.Internal; using Dalamud.Plugin.Internal; diff --git a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs index 9d8dc1e93..54ff4a5ca 100644 --- a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs +++ b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs @@ -5,6 +5,7 @@ using System.Numerics; using Dalamud.Game.Gui; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using ImGuiNET; using Serilog; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs index ec7124042..dc18dbd55 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs @@ -1,4 +1,5 @@ -using Dalamud.Plugin.Ipc.Internal; +using Dalamud.Interface.Utility; +using Dalamud.Plugin.Ipc.Internal; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Data; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs index 1ed5e9e83..e4284a98e 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Numerics; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Data; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs index 01d0b1759..6f19404ad 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs @@ -7,7 +7,8 @@ using System.Text.RegularExpressions; using Dalamud.Data; using Dalamud.Game.Network; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Memory; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs index 57fd03300..64ae041ed 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Objects; +using Dalamud.Interface.Utility; using Dalamud.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs index 7d91cd154..59ca617f5 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Dalamud.Game; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using Dalamud.Logging.Internal; using ImGuiNET; using Serilog; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs index 5ad5868c3..cc38a58ae 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Numerics; +using Dalamud.Interface.Utility; using Dalamud.Plugin.Services; using ImGuiNET; using ImGuiScene; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs index c75230e73..7f020acae 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs @@ -1,6 +1,7 @@ using System.Numerics; using Dalamud.Game.Gui.Toast; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Data; diff --git a/Dalamud/Interface/Internal/Windows/GamepadModeNotifierWindow.cs b/Dalamud/Interface/Internal/Windows/GamepadModeNotifierWindow.cs index e95c510d3..ff5af1556 100644 --- a/Dalamud/Interface/Internal/Windows/GamepadModeNotifierWindow.cs +++ b/Dalamud/Interface/Internal/Windows/GamepadModeNotifierWindow.cs @@ -1,6 +1,7 @@ using System.Numerics; using CheapLoc; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 35fa40013..2b0e27673 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -15,8 +15,9 @@ using Dalamud.Game.Command; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Internal.Notifications; -using Dalamud.Interface.Raii; using Dalamud.Interface.Style; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using Dalamud.Logging.Internal; using Dalamud.Plugin; diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs index 301e43473..6c17a8522 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs @@ -8,7 +8,8 @@ using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Internal.Notifications; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal.Profiles; using Dalamud.Utility; diff --git a/Dalamud/Interface/Internal/Windows/ProfilerWindow.cs b/Dalamud/Interface/Internal/Windows/ProfilerWindow.cs index 2d0f54912..16f253da9 100644 --- a/Dalamud/Interface/Internal/Windows/ProfilerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ProfilerWindow.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Numerics; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Utility.Numerics; using Dalamud.Utility.Timing; diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs b/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs index 3e25b6f5a..4a7bb0413 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs @@ -6,6 +6,7 @@ using System.Numerics; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Internal.Windows.SelfTest.AgingSteps; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Logging.Internal; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs b/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs index 16b7749cb..a3ece0d04 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/SettingsTab.cs @@ -1,5 +1,6 @@ -using System; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; + +using Dalamud.Interface.Utility; namespace Dalamud.Interface.Internal.Windows.Settings; diff --git a/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs index 97d9eac5c..4f77c0502 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/SettingsWindow.cs @@ -5,7 +5,8 @@ using CheapLoc; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; using Dalamud.Interface.Internal.Windows.Settings.Tabs; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using Dalamud.Plugin.Internal; using Dalamud.Utility; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs index 325d0b8b7..9a7236f2f 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs @@ -8,7 +8,8 @@ using System.Numerics; using CheapLoc; using Dalamud.Game.Gui; using Dalamud.Interface.GameFonts; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Internal; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.Game.UI; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs index 85cb8219f..7dd0fa5d1 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabDtr.cs @@ -8,6 +8,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Game.Gui.Dtr; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Settings.Tabs; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs index 62981f4a2..0a0e2528d 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabExperimental.cs @@ -6,6 +6,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; using Dalamud.Interface.Internal.Windows.PluginInstaller; using Dalamud.Interface.Internal.Windows.Settings.Widgets; +using Dalamud.Interface.Utility; using Dalamud.Plugin.Internal; using Dalamud.Utility; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs index 3e801a8c3..b34a13cc5 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabLook.cs @@ -5,6 +5,7 @@ using CheapLoc; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; using Dalamud.Interface.Internal.Windows.Settings.Widgets; +using Dalamud.Interface.Utility; using Dalamud.Utility; using ImGuiNET; using Serilog; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs index 9c635fb99..6adddbc82 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ButtonSettingsEntry.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Settings.Widgets; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs index 3e73454f3..55deb61bc 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/DevPluginsSettingsEntry.cs @@ -11,7 +11,8 @@ using Dalamud.Configuration; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Internal; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs index bc5c2fd0a..1db3c4756 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/GapSettingsEntry.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Settings.Widgets; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs index d1eb43c1f..3edd3ae1d 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/HintSettingsEntry.cs @@ -2,6 +2,7 @@ using System.Numerics; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; namespace Dalamud.Interface.Internal.Windows.Settings.Widgets; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs index 0bb373576..85f8a826f 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/LanguageChooserSettingsEntry.cs @@ -7,6 +7,7 @@ using System.Linq; using CheapLoc; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.Settings.Widgets; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs index 83be6a052..dcbb42089 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/SettingsEntry{T}.cs @@ -7,7 +7,8 @@ using System.Linq; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs index be2e34a57..114de1148 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs @@ -10,7 +10,8 @@ using Dalamud.Configuration; using Dalamud.Configuration.Internal; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Internal; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/StyleEditor/StyleEditorWindow.cs b/Dalamud/Interface/Internal/Windows/StyleEditor/StyleEditorWindow.cs index 419361b3b..3a3e871b0 100644 --- a/Dalamud/Interface/Internal/Windows/StyleEditor/StyleEditorWindow.cs +++ b/Dalamud/Interface/Internal/Windows/StyleEditor/StyleEditorWindow.cs @@ -10,6 +10,7 @@ using Dalamud.Data; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Style; +using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 10180f0c3..f11f124cc 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -9,7 +9,8 @@ using Dalamud.Game; using Dalamud.Game.ClientState; using Dalamud.Game.Gui; using Dalamud.Interface.Animation.EasingFunctions; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using ImGuiNET; using ImGuiScene; diff --git a/Dalamud.Interface/ImGuiClip.cs b/Dalamud/Interface/Utility/ImGuiClip.cs similarity index 97% rename from Dalamud.Interface/ImGuiClip.cs rename to Dalamud/Interface/Utility/ImGuiClip.cs index dc1845a35..e36970885 100644 --- a/Dalamud.Interface/ImGuiClip.cs +++ b/Dalamud/Interface/Utility/ImGuiClip.cs @@ -1,8 +1,11 @@ +using System.Collections.Generic; +using System.Linq; using System.Numerics; -using Dalamud.Interface.Raii; + +using Dalamud.Interface.Utility.Raii; using ImGuiNET; -namespace Dalamud.Interface; +namespace Dalamud.Interface.Utility; public static class ImGuiClip { @@ -132,7 +135,6 @@ public static class ImGuiClip return ~idx; } - // Draw non-random-access data that gets filtered without storing state. // Use GetNecessarySkips first and use its return value for skips. // checkFilter should return true for items that should be displayed and false for those that should be skipped. diff --git a/Dalamud/Interface/ImGuiExtensions.cs b/Dalamud/Interface/Utility/ImGuiExtensions.cs similarity index 98% rename from Dalamud/Interface/ImGuiExtensions.cs rename to Dalamud/Interface/Utility/ImGuiExtensions.cs index be1b99430..21a0d3747 100644 --- a/Dalamud/Interface/ImGuiExtensions.cs +++ b/Dalamud/Interface/Utility/ImGuiExtensions.cs @@ -1,10 +1,9 @@ -using System; using System.Numerics; using System.Text; using ImGuiNET; -namespace Dalamud.Interface; +namespace Dalamud.Interface.Utility; /// /// Class containing various extensions to ImGui, aiding with building custom widgets. diff --git a/Dalamud/Interface/ImGuiHelpers.cs b/Dalamud/Interface/Utility/ImGuiHelpers.cs similarity index 99% rename from Dalamud/Interface/ImGuiHelpers.cs rename to Dalamud/Interface/Utility/ImGuiHelpers.cs index 2356d90e2..dbb873edf 100644 --- a/Dalamud/Interface/ImGuiHelpers.cs +++ b/Dalamud/Interface/Utility/ImGuiHelpers.cs @@ -1,15 +1,14 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Numerics; using Dalamud.Game.ClientState.Keys; -using Dalamud.Interface.Raii; +using Dalamud.Interface.Utility.Raii; using ImGuiNET; using ImGuiScene; -namespace Dalamud.Interface; +namespace Dalamud.Interface.Utility; /// /// Class containing various helper methods for use with ImGui inside Dalamud. @@ -300,7 +299,6 @@ public static class ImGuiHelpers internal static void NewFrame() { GlobalScale = ImGui.GetIO().FontGlobalScale; - InterfaceHelpers.GlobalScale = GlobalScale; } /// diff --git a/Dalamud/Interface/Utility/ImGuiTable.cs b/Dalamud/Interface/Utility/ImGuiTable.cs new file mode 100644 index 000000000..c74bc0a2f --- /dev/null +++ b/Dalamud/Interface/Utility/ImGuiTable.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; + +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; + +namespace Dalamud.Interface.Utility; + +#pragma warning disable SA1618 // GenericTypeParametersMustBeDocumented +#pragma warning disable SA1611 // ElementParametersMustBeDocumented + +/// +/// Helpers for drawing tables. +/// +public static class ImGuiTable +{ + /// + /// Draw a simple table with the given data using the drawRow action. + /// Headers and thus columns and column count are defined by columnTitles. + /// + public static void DrawTable(string label, IEnumerable data, Action drawRow, ImGuiTableFlags flags = ImGuiTableFlags.None, + params string[] columnTitles) + { + if (columnTitles.Length == 0) + return; + + using var table = ImRaii.Table(label, columnTitles.Length, flags); + if (!table) + return; + + foreach (var title in columnTitles) + { + ImGui.TableNextColumn(); + ImGui.TableHeader(title); + } + + foreach (var datum in data) + { + ImGui.TableNextRow(); + drawRow(datum); + } + } + + /// + /// Draw a simple table with the given data using the drawRow action inside a collapsing header. + /// Headers and thus columns and column count are defined by columnTitles. + /// + public static void DrawTabbedTable(string label, IEnumerable data, Action drawRow, ImGuiTableFlags flags = ImGuiTableFlags.None, + params string[] columnTitles) + { + if (ImGui.CollapsingHeader(label)) + DrawTable($"{label}##Table", data, drawRow, flags, columnTitles); + } +} + +#pragma warning restore SA1611 // ElementParametersMustBeDocumented +#pragma warning restore SA1618 // GenericTypeParametersMustBeDocumented diff --git a/Dalamud.Interface/Raii/Color.cs b/Dalamud/Interface/Utility/Raii/Color.cs similarity index 83% rename from Dalamud.Interface/Raii/Color.cs rename to Dalamud/Interface/Utility/Raii/Color.cs index 388e6e737..3cf93b65c 100644 --- a/Dalamud.Interface/Raii/Color.cs +++ b/Dalamud/Interface/Utility/Raii/Color.cs @@ -1,7 +1,10 @@ +using System.Collections.Generic; +using System.Linq; using System.Numerics; + using ImGuiNET; -namespace Dalamud.Interface.Raii; +namespace Dalamud.Interface.Utility.Raii; // Push an arbitrary amount of colors into an object that are all popped when it is disposed. // If condition is false, no color is pushed. @@ -26,7 +29,7 @@ public static partial class ImRaii public sealed class Color : IDisposable { internal static readonly List<(ImGuiCol, uint)> Stack = new(); - private int _count; + private int count; public Color Push(ImGuiCol idx, uint color, bool condition = true) { @@ -34,7 +37,7 @@ public static partial class ImRaii { Stack.Add((idx, ImGui.GetColorU32(idx))); ImGui.PushStyleColor(idx, color); - ++this._count; + ++this.count; } return this; @@ -46,7 +49,7 @@ public static partial class ImRaii { Stack.Add((idx, ImGui.GetColorU32(idx))); ImGui.PushStyleColor(idx, color); - ++this._count; + ++this.count; } return this; @@ -54,13 +57,13 @@ public static partial class ImRaii public void Pop(int num = 1) { - num = Math.Min(num, this._count); - this._count -= num; + num = Math.Min(num, this.count); + this.count -= num; ImGui.PopStyleColor(num); Stack.RemoveRange(Stack.Count - num, num); } public void Dispose() - => this.Pop(this._count); + => this.Pop(this.count); } } diff --git a/Dalamud.Interface/Raii/EndObjects.cs b/Dalamud/Interface/Utility/Raii/EndObjects.cs similarity index 94% rename from Dalamud.Interface/Raii/EndObjects.cs rename to Dalamud/Interface/Utility/Raii/EndObjects.cs index 032f09621..3f2a016b3 100644 --- a/Dalamud.Interface/Raii/EndObjects.cs +++ b/Dalamud/Interface/Utility/Raii/EndObjects.cs @@ -1,13 +1,14 @@ using System.Numerics; + using ImGuiNET; -namespace Dalamud.Interface.Raii; +namespace Dalamud.Interface.Utility.Raii; // Most ImGui widgets with IDisposable interface that automatically destroys them // when created with using variables. public static partial class ImRaii { - private static int _disabledCount = 0; + private static int disabledCount = 0; public static IEndObject Child(string strId) => new EndUnconditionally(ImGui.EndChild, ImGui.BeginChild(strId)); @@ -120,7 +121,7 @@ public static partial class ImRaii public static IEndObject Disabled() { ImGui.BeginDisabled(); - ++_disabledCount; + ++disabledCount; return DisabledEnd(); } @@ -130,24 +131,24 @@ public static partial class ImRaii return new EndConditionally(Nop, false); ImGui.BeginDisabled(); - ++_disabledCount; + ++disabledCount; return DisabledEnd(); } public static IEndObject Enabled() { - var oldCount = _disabledCount; + var oldCount = disabledCount; if (oldCount == 0) return new EndConditionally(Nop, false); void Restore() { - _disabledCount += oldCount; + disabledCount += oldCount; while (--oldCount >= 0) ImGui.BeginDisabled(); } - for (; _disabledCount > 0; --_disabledCount) + for (; disabledCount > 0; --disabledCount) ImGui.EndDisabled(); return new EndUnconditionally(Restore, true); @@ -156,7 +157,7 @@ public static partial class ImRaii private static IEndObject DisabledEnd() => new EndUnconditionally(() => { - --_disabledCount; + --disabledCount; ImGui.EndDisabled(); }, true); @@ -173,6 +174,11 @@ public static partial class ImRaii return new EndUnconditionally(Widget.EndFramedGroup, true); } */ + + // Used to avoid tree pops when flag for no push is set. + private static void Nop() + { + } // Exported interface for RAII. public interface IEndObject : IDisposable @@ -203,7 +209,9 @@ public static partial class ImRaii private struct EndUnconditionally : IEndObject { private Action EndAction { get; } + public bool Success { get; } + public bool Disposed { get; private set; } public EndUnconditionally(Action endAction, bool success) @@ -226,16 +234,18 @@ public static partial class ImRaii // Use end-function only on success. private struct EndConditionally : IEndObject { - private Action EndAction { get; } - public bool Success { get; } - public bool Disposed { get; private set; } - public EndConditionally(Action endAction, bool success) { this.EndAction = endAction; - this.Success = success; - this.Disposed = false; + this.Success = success; + this.Disposed = false; } + + public bool Success { get; } + + public bool Disposed { get; private set; } + + private Action EndAction { get; } public void Dispose() { @@ -247,8 +257,4 @@ public static partial class ImRaii this.Disposed = true; } } - - // Used to avoid tree pops when flag for no push is set. - private static void Nop() - { } } diff --git a/Dalamud.Interface/Raii/Font.cs b/Dalamud/Interface/Utility/Raii/Font.cs similarity index 81% rename from Dalamud.Interface/Raii/Font.cs rename to Dalamud/Interface/Utility/Raii/Font.cs index cdecf457c..2d11bb071 100644 --- a/Dalamud.Interface/Raii/Font.cs +++ b/Dalamud/Interface/Utility/Raii/Font.cs @@ -1,6 +1,6 @@ using ImGuiNET; -namespace Dalamud.Interface.Raii; +namespace Dalamud.Interface.Utility.Raii; // Push an arbitrary amount of fonts into an object that are all popped when it is disposed. // If condition is false, no font is pushed. @@ -18,10 +18,10 @@ public static partial class ImRaii internal static int FontPushCounter = 0; internal static ImFontPtr DefaultPushed; - private int _count; + private int count; public Font() - => this._count = 0; + => this.count = 0; public Font Push(ImFontPtr font, bool condition = true) { @@ -30,7 +30,7 @@ public static partial class ImRaii if (FontPushCounter++ == 0) DefaultPushed = ImGui.GetFont(); ImGui.PushFont(font); - ++this._count; + ++this.count; } return this; @@ -38,14 +38,14 @@ public static partial class ImRaii public void Pop(int num = 1) { - num = Math.Min(num, this._count); - this._count -= num; + num = Math.Min(num, this.count); + this.count -= num; FontPushCounter -= num; while (num-- > 0) ImGui.PopFont(); } public void Dispose() - => this.Pop(this._count); + => this.Pop(this.count); } } diff --git a/Dalamud.Interface/Raii/Id.cs b/Dalamud/Interface/Utility/Raii/Id.cs similarity index 82% rename from Dalamud.Interface/Raii/Id.cs rename to Dalamud/Interface/Utility/Raii/Id.cs index 1248b92f3..51c6438c4 100644 --- a/Dalamud.Interface/Raii/Id.cs +++ b/Dalamud/Interface/Utility/Raii/Id.cs @@ -1,6 +1,6 @@ using ImGuiNET; -namespace Dalamud.Interface.Raii; +namespace Dalamud.Interface.Utility.Raii; // Push an arbitrary amount of ids into an object that are all popped when it is disposed. // If condition is false, no id is pushed. @@ -17,14 +17,14 @@ public static partial class ImRaii public sealed class Id : IDisposable { - private int _count; + private int count; public Id Push(string id, bool condition = true) { if (condition) { ImGui.PushID(id); - ++this._count; + ++this.count; } return this; @@ -35,7 +35,7 @@ public static partial class ImRaii if (condition) { ImGui.PushID(id); - ++this._count; + ++this.count; } return this; @@ -46,7 +46,7 @@ public static partial class ImRaii if (condition) { ImGui.PushID(id); - ++this._count; + ++this.count; } return this; @@ -54,13 +54,13 @@ public static partial class ImRaii public void Pop(int num = 1) { - num = Math.Min(num, this._count); - this._count -= num; + num = Math.Min(num, this.count); + this.count -= num; while (num-- > 0) ImGui.PopID(); } public void Dispose() - => this.Pop(this._count); + => this.Pop(this.count); } } diff --git a/Dalamud.Interface/Raii/Indent.cs b/Dalamud/Interface/Utility/Raii/Indent.cs similarity index 91% rename from Dalamud.Interface/Raii/Indent.cs rename to Dalamud/Interface/Utility/Raii/Indent.cs index 99eab8783..3c8f0f1da 100644 --- a/Dalamud.Interface/Raii/Indent.cs +++ b/Dalamud/Interface/Utility/Raii/Indent.cs @@ -1,6 +1,6 @@ using ImGuiNET; -namespace Dalamud.Interface.Raii; +namespace Dalamud.Interface.Utility.Raii; public static partial class ImRaii { @@ -19,7 +19,7 @@ public static partial class ImRaii if (condition) { if (scaled) - indent *= InterfaceHelpers.GlobalScale; + indent *= ImGuiHelpers.GlobalScale; IndentInternal(indent); this.Indentation += indent; @@ -43,7 +43,7 @@ public static partial class ImRaii public void Pop(float indent, bool scaled = true) { if (scaled) - indent *= InterfaceHelpers.GlobalScale; + indent *= ImGuiHelpers.GlobalScale; IndentInternal(-indent); this.Indentation -= indent; diff --git a/Dalamud.Interface/Raii/Style.cs b/Dalamud/Interface/Utility/Raii/Style.cs similarity index 95% rename from Dalamud.Interface/Raii/Style.cs rename to Dalamud/Interface/Utility/Raii/Style.cs index 2f1fea538..82f51bf88 100644 --- a/Dalamud.Interface/Raii/Style.cs +++ b/Dalamud/Interface/Utility/Raii/Style.cs @@ -1,7 +1,10 @@ +using System.Collections.Generic; +using System.Linq; using System.Numerics; + using ImGuiNET; -namespace Dalamud.Interface.Raii; +namespace Dalamud.Interface.Utility.Raii; // Push an arbitrary amount of styles into an object that are all popped when it is disposed. // If condition is false, no style is pushed. @@ -17,7 +20,7 @@ public static partial class ImRaii // Push styles that revert all current style changes made temporarily. public static Style DefaultStyle() { - var ret = new Style(); + var ret = new Style(); var reverseStack = Style.Stack.GroupBy(p => p.Item1).Select(p => (p.Key, p.First().Item2)).ToArray(); foreach (var (idx, val) in reverseStack) { @@ -34,7 +37,7 @@ public static partial class ImRaii { internal static readonly List<(ImGuiStyleVar, Vector2)> Stack = new(); - private int _count; + private int count; [System.Diagnostics.Conditional("DEBUG")] private static void CheckStyleIdx(ImGuiStyleVar idx, Type type) @@ -115,7 +118,7 @@ public static partial class ImRaii CheckStyleIdx(idx, typeof(float)); Stack.Add((idx, GetStyle(idx))); ImGui.PushStyleVar(idx, value); - ++this._count; + ++this.count; return this; } @@ -128,20 +131,20 @@ public static partial class ImRaii CheckStyleIdx(idx, typeof(Vector2)); Stack.Add((idx, GetStyle(idx))); ImGui.PushStyleVar(idx, value); - ++this._count; + ++this.count; return this; } public void Pop(int num = 1) { - num = Math.Min(num, this._count); - this._count -= num; + num = Math.Min(num, this.count); + this.count -= num; ImGui.PopStyleVar(num); Stack.RemoveRange(Stack.Count - num, num); } public void Dispose() - => this.Pop(this._count); + => this.Pop(this.count); } } diff --git a/Dalamud.Interface/Table/Column.cs b/Dalamud/Interface/Utility/Table/Column.cs similarity index 92% rename from Dalamud.Interface/Table/Column.cs rename to Dalamud/Interface/Utility/Table/Column.cs index 7460ec189..412ba87dc 100644 --- a/Dalamud.Interface/Table/Column.cs +++ b/Dalamud/Interface/Utility/Table/Column.cs @@ -1,6 +1,6 @@ using ImGuiNET; -namespace Dalamud.Interface.Table; +namespace Dalamud.Interface.Utility.Table; public class Column { @@ -27,7 +27,8 @@ public class Column => 0; public virtual void DrawColumn(TItem item, int idx) - { } + { + } public int CompareInv(TItem lhs, TItem rhs) => this.Compare(rhs, lhs); diff --git a/Dalamud.Interface/Table/ColumnFlags.cs b/Dalamud/Interface/Utility/Table/ColumnFlags.cs similarity index 89% rename from Dalamud.Interface/Table/ColumnFlags.cs rename to Dalamud/Interface/Utility/Table/ColumnFlags.cs index 815ddcf76..24670adfc 100644 --- a/Dalamud.Interface/Table/ColumnFlags.cs +++ b/Dalamud/Interface/Utility/Table/ColumnFlags.cs @@ -1,7 +1,9 @@ -using ImGuiNET; -using ImRaii = Dalamud.Interface.Raii.ImRaii; +using System.Collections.Generic; -namespace Dalamud.Interface.Table; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; + +namespace Dalamud.Interface.Utility.Table; public class ColumnFlags : Column where T : struct, Enum { @@ -17,13 +19,14 @@ public class ColumnFlags : Column where T : struct, Enum => default; protected virtual void SetValue(T value, bool enable) - { } + { + } public override bool DrawFilter() { using var id = ImRaii.PushId(this.FilterLabel); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0); - ImGui.SetNextItemWidth(-Table.ArrowWidth * InterfaceHelpers.GlobalScale); + ImGui.SetNextItemWidth(-Table.ArrowWidth * ImGuiHelpers.GlobalScale); var all = this.FilterValue.HasFlag(this.AllFlags); using var color = ImRaii.PushColor(ImGuiCol.FrameBg, 0x803030A0, !all); using var combo = ImRaii.Combo(string.Empty, this.Label, ImGuiComboFlags.NoArrowButton); diff --git a/Dalamud.Interface/Table/ColumnSelect.cs b/Dalamud/Interface/Utility/Table/ColumnSelect.cs similarity index 66% rename from Dalamud.Interface/Table/ColumnSelect.cs rename to Dalamud/Interface/Utility/Table/ColumnSelect.cs index 5ef276b06..fb463700c 100644 --- a/Dalamud.Interface/Table/ColumnSelect.cs +++ b/Dalamud/Interface/Utility/Table/ColumnSelect.cs @@ -1,7 +1,9 @@ -using ImGuiNET; -using ImRaii = Dalamud.Interface.Raii.ImRaii; +using System.Collections.Generic; -namespace Dalamud.Interface.Table; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; + +namespace Dalamud.Interface.Utility.Table; public class ColumnSelect : Column where T : struct, Enum, IEquatable { @@ -18,26 +20,26 @@ public class ColumnSelect : Column where T : struct, Enum, IEqu => this.FilterValue = value; public T FilterValue; - protected int Idx = -1; + protected int idx = -1; public override bool DrawFilter() { using var id = ImRaii.PushId(this.FilterLabel); using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0); - ImGui.SetNextItemWidth(-Table.ArrowWidth * InterfaceHelpers.GlobalScale); - using var combo = ImRaii.Combo(string.Empty, this.Idx < 0 ? this.Label : this.Names[this.Idx]); - if(!combo) + ImGui.SetNextItemWidth(-Table.ArrowWidth * ImGuiHelpers.GlobalScale); + using var combo = ImRaii.Combo(string.Empty, this.idx < 0 ? this.Label : this.Names[this.idx]); + if (!combo) return false; var ret = false; for (var i = 0; i < this.Names.Length; ++i) { if (this.FilterValue.Equals(this.Values[i])) - this.Idx = i; - if (!ImGui.Selectable(this.Names[i], this.Idx == i) || this.Idx == i) + this.idx = i; + if (!ImGui.Selectable(this.Names[i], this.idx == i) || this.idx == i) continue; - this.Idx = i; + this.idx = i; this.SetValue(this.Values[i]); ret = true; } diff --git a/Dalamud.Interface/Table/ColumnString.cs b/Dalamud/Interface/Utility/Table/ColumnString.cs similarity index 75% rename from Dalamud.Interface/Table/ColumnString.cs rename to Dalamud/Interface/Utility/Table/ColumnString.cs index dcd43b23c..3f9d2df91 100644 --- a/Dalamud.Interface/Table/ColumnString.cs +++ b/Dalamud/Interface/Utility/Table/ColumnString.cs @@ -1,8 +1,9 @@ using System.Text.RegularExpressions; -using Dalamud.Interface.Raii; + +using Dalamud.Interface.Utility.Raii; using ImGuiNET; -namespace Dalamud.Interface.Table; +namespace Dalamud.Interface.Utility.Table; public class ColumnString : Column { @@ -10,7 +11,7 @@ public class ColumnString : Column => this.Flags &= ~ImGuiTableColumnFlags.NoResize; public string FilterValue = string.Empty; - protected Regex? FilterRegex; + protected Regex? filterRegex; public virtual string ToName(TItem item) => item!.ToString() ?? string.Empty; @@ -22,7 +23,7 @@ public class ColumnString : Column { using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0); - ImGui.SetNextItemWidth(-Table.ArrowWidth * InterfaceHelpers.GlobalScale); + ImGui.SetNextItemWidth(-Table.ArrowWidth * ImGuiHelpers.GlobalScale); var tmp = this.FilterValue; if (!ImGui.InputTextWithHint(this.FilterLabel, this.Label, ref tmp, 256) || tmp == this.FilterValue) return false; @@ -30,11 +31,11 @@ public class ColumnString : Column this.FilterValue = tmp; try { - this.FilterRegex = new Regex(this.FilterValue, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + this.filterRegex = new Regex(this.FilterValue, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); } catch { - this.FilterRegex = null; + this.filterRegex = null; } return true; @@ -46,10 +47,10 @@ public class ColumnString : Column if (this.FilterValue.Length == 0) return true; - return this.FilterRegex?.IsMatch(name) ?? name.Contains(this.FilterValue, StringComparison.OrdinalIgnoreCase); + return this.filterRegex?.IsMatch(name) ?? name.Contains(this.FilterValue, StringComparison.OrdinalIgnoreCase); } - public override void DrawColumn(TItem item, int _) + public override void DrawColumn(TItem item, int idx) { ImGui.TextUnformatted(this.ToName(item)); } diff --git a/Dalamud.Interface/Table/Table.cs b/Dalamud/Interface/Utility/Table/Table.cs similarity index 64% rename from Dalamud.Interface/Table/Table.cs rename to Dalamud/Interface/Utility/Table/Table.cs index 74fb0bc5c..86653e834 100644 --- a/Dalamud.Interface/Table/Table.cs +++ b/Dalamud/Interface/Utility/Table/Table.cs @@ -1,8 +1,12 @@ +using System.Collections.Generic; +using System.Linq; using System.Numerics; -using ImGuiNET; -using ImRaii = Dalamud.Interface.Raii.ImRaii; -namespace Dalamud.Interface.Table; +using Dalamud.Interface.Utility.Raii; +using Dalamud.Utility; +using ImGuiNET; + +namespace Dalamud.Interface.Utility.Table; public static class Table { @@ -11,18 +15,20 @@ public static class Table public class Table { - protected bool FilterDirty = true; - protected bool SortDirty = true; protected readonly ICollection Items; - internal readonly List<(T, int)> FilteredItems; + internal readonly List<(T, int)> FilteredItems; - protected readonly string Label; + protected readonly string Label; protected readonly Column[] Headers; - protected float ItemHeight { get; set; } - public float ExtraHeight { get; set; } = 0; + protected bool filterDirty = true; + protected bool sortDirty = true; - private int _currentIdx = 0; + protected float ItemHeight { get; set; } + + public float ExtraHeight { get; set; } = 0; + + private int currentIdx = 0; protected bool Sortable { @@ -30,7 +36,7 @@ public class Table set => this.Flags = value ? this.Flags | ImGuiTableFlags.Sortable : this.Flags & ~ImGuiTableFlags.Sortable; } - protected int SortIdx = -1; + protected int sortIdx = -1; public ImGuiTableFlags Flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.Sortable @@ -54,10 +60,10 @@ public class Table public Table(string label, ICollection items, params Column[] headers) { - this.Label = label; - this.Items = items; - this.Headers = headers; - this.FilteredItems = new List<(T, int)>(this.Items.Count); + this.Label = label; + this.Items = items; + this.Headers = headers; + this.FilteredItems = new List<(T, int)>(this.Items.Count); this.VisibleColumns = this.Headers.Length; } @@ -73,7 +79,8 @@ public class Table => throw new NotImplementedException(); protected virtual void PreDraw() - { } + { + } private void SortInternal() { @@ -81,29 +88,30 @@ public class Table return; var sortSpecs = ImGui.TableGetSortSpecs(); - this.SortDirty |= sortSpecs.SpecsDirty; + this.sortDirty |= sortSpecs.SpecsDirty; - if (!this.SortDirty) + if (!this.sortDirty) return; - this.SortIdx = sortSpecs.Specs.ColumnIndex; + this.sortIdx = sortSpecs.Specs.ColumnIndex; - if (this.Headers.Length <= this.SortIdx) - this.SortIdx = 0; + if (this.Headers.Length <= this.sortIdx) + this.sortIdx = 0; - if (sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending) - this.FilteredItems.StableSort((a, b) => this.Headers[this.SortIdx].Compare(a.Item1, b.Item1)); - else if (sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending) - this.FilteredItems.StableSort((a, b) => this.Headers[this.SortIdx].CompareInv(a.Item1, b.Item1)); - else - this.SortIdx = -1; - this.SortDirty = false; - sortSpecs.SpecsDirty = false; + if (sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending) + this.FilteredItems.StableSort((a, b) => this.Headers[this.sortIdx].Compare(a.Item1, b.Item1)); + else if (sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending) + this.FilteredItems.StableSort((a, b) => this.Headers[this.sortIdx].CompareInv(a.Item1, b.Item1)); + else + this.sortIdx = -1; + + this.sortDirty = false; + sortSpecs.SpecsDirty = false; } private void UpdateFilter() { - if (!this.FilterDirty) + if (!this.filterDirty) return; this.FilteredItems.Clear(); @@ -115,20 +123,20 @@ public class Table idx++; } - this.FilterDirty = false; - this.SortDirty = true; + this.filterDirty = false; + this.sortDirty = true; } - private void DrawItem((T, int) pair) + private void DrawItem((T Item, int Index) pair) { - var column = 0; - using var id = ImRaii.PushId(this._currentIdx); - this._currentIdx = pair.Item2; + var column = 0; + using var id = ImRaii.PushId(this.currentIdx); + this.currentIdx = pair.Index; foreach (var header in this.Headers) { id.Push(column++); if (ImGui.TableNextColumn()) - header.DrawColumn(pair.Item1, pair.Item2); + header.DrawColumn(pair.Item, pair.Index); id.Pop(); } } @@ -136,7 +144,7 @@ public class Table private void DrawTableInternal() { using var table = ImRaii.Table("Table", this.Headers.Length, this.Flags, - ImGui.GetContentRegionAvail() - this.ExtraHeight * Vector2.UnitY * InterfaceHelpers.GlobalScale); + ImGui.GetContentRegionAvail() - this.ExtraHeight * Vector2.UnitY * ImGuiHelpers.GlobalScale); if (!table) return; @@ -162,11 +170,11 @@ public class Table ImGui.SameLine(); style.Pop(); if (header.DrawFilter()) - this.FilterDirty = true; + this.filterDirty = true; } this.SortInternal(); - this._currentIdx = 0; + this.currentIdx = 0; ImGuiClip.ClippedDraw(this.FilteredItems, this.DrawItem, this.ItemHeight); } } diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs index 39c61566b..a339b807d 100644 --- a/Dalamud/Interface/Windowing/Window.cs +++ b/Dalamud/Interface/Windowing/Window.cs @@ -2,6 +2,7 @@ using System.Numerics; using Dalamud.Configuration.Internal; using Dalamud.Game.ClientState.Keys; +using Dalamud.Interface.Utility; using FFXIVClientStructs.FFXIV.Client.UI; using ImGuiNET; @@ -223,6 +224,7 @@ public abstract class Window /// /// Draw the window via ImGui. /// + /// Configuration instance used to check if certain window management features should be enabled. internal void DrawInternal(DalamudConfiguration? configuration) { this.PreOpenCheck(); diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 887994f30..e91195793 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -53,12 +53,6 @@ namespace Dalamud.Plugin.Internal; #pragma warning restore SA1015 internal partial class PluginManager : IDisposable, IServiceType { - /// - /// The current Dalamud API level, used to handle breaking changes. Only plugins with this level will be loaded. - /// As of Dalamud 9.x, this always matches the major version number of Dalamud. - /// - public static int DalamudApiLevel => Assembly.GetExecutingAssembly().GetName().Version!.Major; - /// /// Default time to wait between plugin unload and plugin assembly unload. /// @@ -88,6 +82,11 @@ internal partial class PluginManager : IDisposable, IServiceType [ServiceManager.ServiceDependency] private readonly HappyHttpClient happyHttpClient = Service.Get(); + static PluginManager() + { + DalamudApiLevel = typeof(PluginManager).Assembly.GetName().Version!.Major; + } + [ServiceManager.ServiceConstructor] private PluginManager() { @@ -149,6 +148,12 @@ internal partial class PluginManager : IDisposable, IServiceType /// public event Action? OnAvailablePluginsChanged; + /// + /// Gets the current Dalamud API level, used to handle breaking changes. Only plugins with this level will be loaded. + /// As of Dalamud 9.x, this always matches the major version number of Dalamud. + /// + public static int DalamudApiLevel { get; private set; } + /// /// Gets a copy of the list of all loaded plugins. /// diff --git a/Dalamud/Plugin/Services/IGameConfig.cs b/Dalamud/Plugin/Services/IGameConfig.cs index 98f6160cc..69a611114 100644 --- a/Dalamud/Plugin/Services/IGameConfig.cs +++ b/Dalamud/Plugin/Services/IGameConfig.cs @@ -83,7 +83,7 @@ public interface IGameConfig /// Attempts to get the properties of a String option from the System section. /// /// Option to get the properties of. - /// Details of the option: Default Value + /// Details of the option: Default Value. /// A value representing the success. public bool TryGet(SystemConfigOption option, out StringConfigProperties? properties); @@ -139,7 +139,7 @@ public interface IGameConfig /// Attempts to get the properties of a String option from the UiConfig section. /// /// Option to get the properties of. - /// Details of the option: Default Value + /// Details of the option: Default Value. /// A value representing the success. public bool TryGet(UiConfigOption option, out StringConfigProperties? properties); @@ -195,7 +195,7 @@ public interface IGameConfig /// Attempts to get the properties of a String option from the UiControl section. /// /// Option to get the properties of. - /// Details of the option: Default Value + /// Details of the option: Default Value. /// A value representing the success. public bool TryGet(UiControlOption option, out StringConfigProperties? properties); diff --git a/Dalamud/Plugin/Services/IKeyState.cs b/Dalamud/Plugin/Services/IKeyState.cs index c2bca7347..de78978ca 100644 --- a/Dalamud/Plugin/Services/IKeyState.cs +++ b/Dalamud/Plugin/Services/IKeyState.cs @@ -1,7 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; + using Dalamud.Game.ClientState.Keys; -using PInvoke; namespace Dalamud.Plugin.Services; diff --git a/Dalamud.Interface/ArrayExtensions.cs b/Dalamud/Utility/ArrayExtensions.cs similarity index 80% rename from Dalamud.Interface/ArrayExtensions.cs rename to Dalamud/Utility/ArrayExtensions.cs index 68bf52a29..afb1511e3 100644 --- a/Dalamud.Interface/ArrayExtensions.cs +++ b/Dalamud/Utility/ArrayExtensions.cs @@ -1,7 +1,13 @@ +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; -namespace Dalamud.Interface; +namespace Dalamud.Utility; +[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1618:Generic type parameters should be documented", Justification = "Reviewed,")] +[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "Reviewed,")] +[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1615:Element return value should be documented", Justification = "Reviewed,")] +[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1611:Element parameters should be documented", Justification = "Reviewed,")] internal static class ArrayExtensions { /// Iterate over enumerables with additional index. @@ -16,7 +22,6 @@ internal static class ArrayExtensions public static IEnumerable WithoutValue(this IEnumerable<(T Value, int Index)> list) => list.Select(x => x.Index); - // Find the index of the first object fulfilling predicate's criteria in the given list. // Returns -1 if no such object is found. public static int IndexOf(this IEnumerable array, Predicate predicate) diff --git a/Dalamud/Utility/FuzzyMatcher.cs b/Dalamud/Utility/FuzzyMatcher.cs index 647c9586d..9ac71d8bb 100644 --- a/Dalamud/Utility/FuzzyMatcher.cs +++ b/Dalamud/Utility/FuzzyMatcher.cs @@ -6,6 +6,9 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +#pragma warning disable SA1600 +#pragma warning disable SA1602 + internal readonly ref struct FuzzyMatcher { private static readonly (int, int)[] EmptySegArray = Array.Empty<(int, int)>(); @@ -13,31 +16,31 @@ internal readonly ref struct FuzzyMatcher private readonly string needleString = string.Empty; private readonly ReadOnlySpan needleSpan = ReadOnlySpan.Empty; private readonly int needleFinalPosition = -1; - private readonly (int start, int end)[] needleSegments = EmptySegArray; + private readonly (int Start, int End)[] needleSegments = EmptySegArray; private readonly MatchMode mode = MatchMode.Simple; public FuzzyMatcher(string term, MatchMode matchMode) { - needleString = term; - needleSpan = needleString.AsSpan(); - needleFinalPosition = needleSpan.Length - 1; - mode = matchMode; + this.needleString = term; + this.needleSpan = this.needleString.AsSpan(); + this.needleFinalPosition = this.needleSpan.Length - 1; + this.mode = matchMode; switch (matchMode) { case MatchMode.FuzzyParts: - needleSegments = FindNeedleSegments(needleSpan); + this.needleSegments = FindNeedleSegments(this.needleSpan); break; case MatchMode.Fuzzy: case MatchMode.Simple: - needleSegments = EmptySegArray; + this.needleSegments = EmptySegArray; break; default: throw new ArgumentOutOfRangeException(nameof(matchMode), matchMode, null); } } - private static (int start, int end)[] FindNeedleSegments(ReadOnlySpan span) + private static (int Start, int End)[] FindNeedleSegments(ReadOnlySpan span) { var segments = new List<(int, int)>(); var wordStart = -1; @@ -66,37 +69,39 @@ internal readonly ref struct FuzzyMatcher return segments.ToArray(); } +#pragma warning disable SA1202 public int Matches(string value) +#pragma warning restore SA1202 { - if (needleFinalPosition < 0) + if (this.needleFinalPosition < 0) { return 0; } - if (mode == MatchMode.Simple) + if (this.mode == MatchMode.Simple) { - return value.Contains(needleString) ? 1 : 0; + return value.Contains(this.needleString) ? 1 : 0; } var haystack = value.AsSpan(); - if (mode == MatchMode.Fuzzy) + if (this.mode == MatchMode.Fuzzy) { - return GetRawScore(haystack, 0, needleFinalPosition); + return this.GetRawScore(haystack, 0, this.needleFinalPosition); } - if (mode == MatchMode.FuzzyParts) + if (this.mode == MatchMode.FuzzyParts) { - if (needleSegments.Length < 2) + if (this.needleSegments.Length < 2) { - return GetRawScore(haystack, 0, needleFinalPosition); + return this.GetRawScore(haystack, 0, this.needleFinalPosition); } var total = 0; - for (var i = 0; i < needleSegments.Length; i++) + for (var i = 0; i < this.needleSegments.Length; i++) { - var (start, end) = needleSegments[i]; - var cur = GetRawScore(haystack, start, end); + var (start, end) = this.needleSegments[i]; + var cur = this.GetRawScore(haystack, start, end); if (cur == 0) { return 0; @@ -116,7 +121,7 @@ internal readonly ref struct FuzzyMatcher var max = 0; for (var i = 0; i < values.Length; i++) { - var cur = Matches(values[i]); + var cur = this.Matches(values[i]); if (cur > max) { max = cur; @@ -128,7 +133,7 @@ internal readonly ref struct FuzzyMatcher private int GetRawScore(ReadOnlySpan haystack, int needleStart, int needleEnd) { - var (startPos, gaps, consecutive, borderMatches, endPos) = FindForward(haystack, needleStart, needleEnd); + var (startPos, gaps, consecutive, borderMatches, endPos) = this.FindForward(haystack, needleStart, needleEnd); if (startPos < 0) { return 0; @@ -140,7 +145,7 @@ internal readonly ref struct FuzzyMatcher // PluginLog.Debug( // $"['{needleString.Substring(needleStart, needleEnd - needleStart + 1)}' in '{haystack}'] fwd: needleSize={needleSize} startPos={startPos} gaps={gaps} consecutive={consecutive} borderMatches={borderMatches} score={score}"); - (startPos, gaps, consecutive, borderMatches) = FindReverse(haystack, endPos, needleStart, needleEnd); + (startPos, gaps, consecutive, borderMatches) = this.FindReverse(haystack, endPos, needleStart, needleEnd); var revScore = CalculateRawScore(needleSize, startPos, gaps, consecutive, borderMatches); // PluginLog.Debug( // $"['{needleString.Substring(needleStart, needleEnd - needleStart + 1)}' in '{haystack}'] rev: needleSize={needleSize} startPos={startPos} gaps={gaps} consecutive={consecutive} borderMatches={borderMatches} score={revScore}"); @@ -149,7 +154,9 @@ internal readonly ref struct FuzzyMatcher } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#pragma warning disable SA1204 private static int CalculateRawScore(int needleSize, int startPos, int gaps, int consecutive, int borderMatches) +#pragma warning restore SA1204 { var score = 100 + needleSize * 3 @@ -162,7 +169,7 @@ internal readonly ref struct FuzzyMatcher return score < 1 ? 1 : score; } - private (int startPos, int gaps, int consecutive, int borderMatches, int haystackIndex) FindForward( + private (int StartPos, int Gaps, int Consecutive, int BorderMatches, int HaystackIndex) FindForward( ReadOnlySpan haystack, int needleStart, int needleEnd) { var needleIndex = needleStart; @@ -175,7 +182,7 @@ internal readonly ref struct FuzzyMatcher for (var haystackIndex = 0; haystackIndex < haystack.Length; haystackIndex++) { - if (haystack[haystackIndex] == needleSpan[needleIndex]) + if (haystack[haystackIndex] == this.needleSpan[needleIndex]) { #if BORDER_MATCHING if (haystackIndex > 0) @@ -217,8 +224,8 @@ internal readonly ref struct FuzzyMatcher return (-1, 0, 0, 0, 0); } - private (int startPos, int gaps, int consecutive, int borderMatches) FindReverse(ReadOnlySpan haystack, - int haystackLastMatchIndex, int needleStart, int needleEnd) + private (int StartPos, int Gaps, int Consecutive, int BorderMatches) FindReverse( + ReadOnlySpan haystack, int haystackLastMatchIndex, int needleStart, int needleEnd) { var needleIndex = needleEnd; var revLastMatchIndex = haystack.Length + 10; @@ -229,7 +236,7 @@ internal readonly ref struct FuzzyMatcher for (var haystackIndex = haystackLastMatchIndex; haystackIndex >= 0; haystackIndex--) { - if (haystack[haystackIndex] == needleSpan[needleIndex]) + if (haystack[haystackIndex] == this.needleSpan[needleIndex]) { #if BORDER_MATCHING if (haystackIndex > 0) @@ -265,9 +272,12 @@ internal readonly ref struct FuzzyMatcher } } -public enum MatchMode +internal enum MatchMode { Simple, Fuzzy, - FuzzyParts + FuzzyParts, } + +#pragma warning restore SA1600 +#pragma warning restore SA1602 diff --git a/Dalamud.Interface/StableInsertionSortExtension.cs b/Dalamud/Utility/StableInsertionSortExtension.cs similarity index 57% rename from Dalamud.Interface/StableInsertionSortExtension.cs rename to Dalamud/Utility/StableInsertionSortExtension.cs index d2884f838..f7c9b43be 100644 --- a/Dalamud.Interface/StableInsertionSortExtension.cs +++ b/Dalamud/Utility/StableInsertionSortExtension.cs @@ -1,9 +1,21 @@ +using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; -namespace Dalamud.Interface; +namespace Dalamud.Utility; +/// +/// Extensions methods providing stable insertion sorts for IList. +/// internal static class StableInsertionSortExtension { + /// + /// Perform a stable sort on a list. + /// + /// The list to sort. + /// Selector to order by. + /// Element type. + /// Selected type. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static void StableSort(this IList list, Func selector) { @@ -13,6 +25,12 @@ internal static class StableInsertionSortExtension list[i] = tmpList[i]; } + /// + /// Perform a stable sort on a list. + /// + /// The list to sort. + /// Comparer to use when comparing items. + /// Element type. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static void StableSort(this IList list, Comparison comparer) { diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 53c570e54..5f2e4d5bf 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -17,6 +17,7 @@ using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; using Dalamud.Logging.Internal; using Dalamud.Networking.Http; using ImGuiNET; diff --git a/targets/Dalamud.Plugin.targets b/targets/Dalamud.Plugin.targets index 4a5f9e97e..2f8e029eb 100644 --- a/targets/Dalamud.Plugin.targets +++ b/targets/Dalamud.Plugin.targets @@ -18,7 +18,6 @@ - From 8ecc00f75ff8f0ba57d5a32c32d683a14d41a303 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 4 Aug 2023 19:37:43 +0200 Subject: [PATCH 025/120] refactor: move data widgets to correct namespace --- Dalamud/Interface/Internal/Windows/Data/DataWindow.cs | 1 + .../Internal/Windows/Data/Widgets/AddonInspectorWidget.cs | 2 +- .../Interface/Internal/Windows/Data/Widgets/AddonWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/AddressesWidget.cs | 3 +-- .../Internal/Windows/Data/Widgets/AetherytesWidget.cs | 2 +- .../Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs | 6 ++---- .../Internal/Windows/Data/Widgets/BuddyListWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/CommandWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/ConditionWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/ConfigurationWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/DataShareWidget.cs | 2 +- .../Interface/Internal/Windows/Data/Widgets/DtrBarWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/FateTableWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/FlyTextWidget.cs | 6 ++---- .../Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs | 3 +-- .../Internal/Windows/Data/Widgets/GamepadWidget.cs | 6 ++---- .../Interface/Internal/Windows/Data/Widgets/GaugeWidget.cs | 2 +- .../Interface/Internal/Windows/Data/Widgets/HookWidget.cs | 6 ++---- .../Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs | 6 ++---- .../Internal/Windows/Data/Widgets/KeyStateWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs | 4 +--- .../Internal/Windows/Data/Widgets/ObjectTableWidget.cs | 6 ++---- .../Internal/Windows/Data/Widgets/PartyListWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/PluginIpcWidget.cs | 6 ++---- .../Internal/Windows/Data/Widgets/SeFontTestWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/StartInfoWidget.cs | 2 +- .../Interface/Internal/Windows/Data/Widgets/TargetWidget.cs | 2 +- .../Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs | 5 ++--- .../Interface/Internal/Windows/Data/Widgets/TexWidget.cs | 3 +-- .../Interface/Internal/Windows/Data/Widgets/ToastWidget.cs | 3 +-- .../Internal/Windows/Data/Widgets/UIColorWidget.cs | 3 +-- 32 files changed, 40 insertions(+), 61 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs index 54ff4a5ca..60024c3d5 100644 --- a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs +++ b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs @@ -5,6 +5,7 @@ using System.Numerics; using Dalamud.Game.Gui; using Dalamud.Interface.Components; +using Dalamud.Interface.Internal.Windows.Data.Widgets; using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonInspectorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonInspectorWidget.cs index 977037cc5..af2e6dc2a 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonInspectorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonInspectorWidget.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying addon inspector. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonWidget.cs index b26b7e311..d378dd63d 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddonWidget.cs @@ -3,7 +3,7 @@ using Dalamud.Memory; using Dalamud.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying Addon Data. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs index 606fedadd..b998fea08 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; - using Dalamud.Game; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget to display resolved .text sigs. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AetherytesWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AetherytesWidget.cs index cc4771847..951417456 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AetherytesWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AetherytesWidget.cs @@ -1,7 +1,7 @@ using Dalamud.Game.ClientState.Aetherytes; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying aetheryte table. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs index df98f99a6..2680b29cc 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs @@ -1,10 +1,8 @@ -using System; -using System.Numerics; - +using System.Numerics; using Dalamud.Memory; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying AtkArrayData. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/BuddyListWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/BuddyListWidget.cs index 2aeb9d10d..80d6fdeb9 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/BuddyListWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/BuddyListWidget.cs @@ -2,7 +2,7 @@ using Dalamud.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying data about the Buddy List. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/CommandWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/CommandWidget.cs index e415431ba..136b9356f 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/CommandWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/CommandWidget.cs @@ -1,7 +1,7 @@ using Dalamud.Game.Command; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying command info. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ConditionWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ConditionWidget.cs index a5224589f..cb6960b62 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ConditionWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ConditionWidget.cs @@ -1,7 +1,7 @@ using Dalamud.Game.ClientState.Conditions; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying current character condition flags. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ConfigurationWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ConfigurationWidget.cs index 3922f22b7..9e490ab1f 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ConfigurationWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ConfigurationWidget.cs @@ -1,7 +1,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Utility; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying configuration info. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs index dc18dbd55..a33cc6cda 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/DataShareWidget.cs @@ -2,7 +2,7 @@ using Dalamud.Plugin.Ipc.Internal; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying plugin data share modules. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/DtrBarWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/DtrBarWidget.cs index 6d3a67e1a..f668c4574 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/DtrBarWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/DtrBarWidget.cs @@ -2,7 +2,7 @@ using Dalamud.Game.Gui.Dtr; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying dtr test. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FateTableWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FateTableWidget.cs index 779032f1d..be3183cd8 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FateTableWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FateTableWidget.cs @@ -1,7 +1,7 @@ using Dalamud.Game.ClientState.Fates; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying the Fate Table. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs index 99c1a3e02..699938e98 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs @@ -1,10 +1,8 @@ -using System; -using System.Numerics; - +using System.Numerics; using Dalamud.Game.Gui.FlyText; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying fly text info. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs index e4284a98e..87744c809 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; - using Dalamud.Interface.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget to display FontAwesome Symbols. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/GamepadWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/GamepadWidget.cs index 1a4408d53..a49fc131a 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/GamepadWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/GamepadWidget.cs @@ -1,9 +1,7 @@ -using System; - -using Dalamud.Game.ClientState.GamePad; +using Dalamud.Game.ClientState.GamePad; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying gamepad info. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/GaugeWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/GaugeWidget.cs index 02862b33d..1f7770e74 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/GaugeWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/GaugeWidget.cs @@ -4,7 +4,7 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying job gauge data. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs index aa565b1e6..b70883c36 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs @@ -1,12 +1,10 @@ -using System; -using System.Runtime.InteropServices; - +using System.Runtime.InteropServices; using Dalamud.Hooking; using ImGuiNET; using PInvoke; using Serilog; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying hook information. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs index 8afce718f..bb0777bc8 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs @@ -1,10 +1,8 @@ -using System; - -using Dalamud.Interface.Internal.Notifications; +using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Windowing; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying ImGui test. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/KeyStateWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/KeyStateWidget.cs index accc48b4b..02f0a2781 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/KeyStateWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/KeyStateWidget.cs @@ -2,7 +2,7 @@ using Dalamud.Interface.Colors; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying keyboard state. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs index 6f19404ad..e37423c33 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text.RegularExpressions; - using Dalamud.Data; using Dalamud.Game.Network; using Dalamud.Interface.Utility; @@ -12,7 +10,7 @@ using Dalamud.Interface.Utility.Raii; using Dalamud.Memory; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget to display the current packets. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs index dd41315f2..f5dfbb51b 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs @@ -1,13 +1,11 @@ -using System; -using System.Numerics; - +using System.Numerics; using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.Gui; using Dalamud.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget to display the Object Table. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/PartyListWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/PartyListWidget.cs index c5ac1fb8f..e923947b7 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/PartyListWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/PartyListWidget.cs @@ -2,7 +2,7 @@ using Dalamud.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying information about the current party. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/PluginIpcWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/PluginIpcWidget.cs index 9aae9bba3..b22250fe0 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/PluginIpcWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/PluginIpcWidget.cs @@ -1,12 +1,10 @@ -using System; - -using Dalamud.Plugin.Ipc; +using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc.Internal; using Dalamud.Utility; using ImGuiNET; using Serilog; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for testing plugin IPC systems. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeFontTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeFontTestWidget.cs index a642c439d..feacbbd48 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeFontTestWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeFontTestWidget.cs @@ -1,7 +1,7 @@ using Dalamud.Game.Text; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying test data for SE Font Symbols. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs index f414e0957..c0735f8cc 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs @@ -2,7 +2,7 @@ using ImGuiNET; using Newtonsoft.Json; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget to display the currently set server opcodes. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs index 656efe388..18979251c 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs @@ -1,7 +1,7 @@ using ImGuiNET; using Newtonsoft.Json; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying start info. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs index 64ae041ed..8c11b5a6d 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TargetWidget.cs @@ -4,7 +4,7 @@ using Dalamud.Interface.Utility; using Dalamud.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying target info. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs index 59ca617f5..de9d8dc4f 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs @@ -1,9 +1,8 @@ // ReSharper disable MethodSupportsCancellation // Using alternative method of cancelling tasks by throwing exceptions. -using System; + using System.Reflection; using System.Threading; using System.Threading.Tasks; - using Dalamud.Game; using Dalamud.Interface.Colors; using Dalamud.Interface.Utility; @@ -11,7 +10,7 @@ using Dalamud.Logging.Internal; using ImGuiNET; using Serilog; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying task scheduler test. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs index cc38a58ae..a42351f1a 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; using System.IO; using System.Numerics; - using Dalamud.Interface.Utility; using Dalamud.Plugin.Services; using ImGuiNET; using ImGuiScene; using Serilog; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying texture test. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs index 7f020acae..7b147da29 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs @@ -1,10 +1,9 @@ using System.Numerics; - using Dalamud.Game.Gui.Toast; using Dalamud.Interface.Utility; using ImGuiNET; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying toast test. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs index 1d0ccdce6..2f281538a 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs @@ -1,10 +1,9 @@ using System.Numerics; - using Dalamud.Data; using ImGuiNET; using Lumina.Excel.GeneratedSheets; -namespace Dalamud.Interface.Internal.Windows.Data; +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// /// Widget for displaying all UI Colors from Lumina. From 458ae57918721b7ebab88fab590f0aa4dbd78a7f Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 4 Aug 2023 21:52:57 +0200 Subject: [PATCH 026/120] refactor: remove Hook.compatHookImpl, make abstract --- Dalamud/Hooking/Hook.cs | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs index 558b6bde1..2e785191c 100644 --- a/Dalamud/Hooking/Hook.cs +++ b/Dalamud/Hooking/Hook.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; @@ -13,7 +12,7 @@ namespace Dalamud.Hooking; /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. /// /// Delegate type to represents a function prototype. This must be the same prototype as original function do. -public class Hook : IDisposable, IDalamudHook where T : Delegate +public abstract class Hook : IDisposable, IDalamudHook where T : Delegate { #pragma warning disable SA1310 // ReSharper disable once InconsistentNaming @@ -24,8 +23,6 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate private readonly IntPtr address; - private readonly Hook? compatHookImpl; - /// /// Initializes a new instance of the class. /// @@ -52,28 +49,19 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate /// Gets a delegate function that can be used to call the actual function as if function is not hooked yet. /// /// Hook is already disposed. - public virtual T Original => this.compatHookImpl != null ? this.compatHookImpl!.Original : throw new NotImplementedException(); + public virtual T Original => throw new NotImplementedException(); /// /// Gets a delegate function that can be used to call the actual function as if function is not hooked yet. /// This can be called even after Dispose. /// public T OriginalDisposeSafe - { - get - { - if (this.compatHookImpl != null) - return this.compatHookImpl!.OriginalDisposeSafe; - if (this.IsDisposed) - return Marshal.GetDelegateForFunctionPointer(this.address); - return this.Original; - } - } + => this.IsDisposed ? Marshal.GetDelegateForFunctionPointer(this.address) : this.Original; /// /// Gets a value indicating whether or not the hook is enabled. /// - public virtual bool IsEnabled => this.compatHookImpl != null ? this.compatHookImpl!.IsEnabled : throw new NotImplementedException(); + public virtual bool IsEnabled => throw new NotImplementedException(); /// /// Gets a value indicating whether or not the hook has been disposed. @@ -81,7 +69,7 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate public bool IsDisposed { get; private set; } /// - public virtual string BackendName => this.compatHookImpl != null ? this.compatHookImpl!.BackendName : throw new NotImplementedException(); + public virtual string BackendName => throw new NotImplementedException(); /// /// Creates a hook by rewriting import table address. @@ -230,32 +218,18 @@ public class Hook : IDisposable, IDalamudHook where T : Delegate if (this.IsDisposed) return; - this.compatHookImpl?.Dispose(); - this.IsDisposed = true; } /// /// Starts intercepting a call to the function. /// - public virtual void Enable() - { - if (this.compatHookImpl != null) - this.compatHookImpl.Enable(); - else - throw new NotImplementedException(); - } + public virtual void Enable() => throw new NotImplementedException(); /// /// Stops intercepting a call to the function. /// - public virtual void Disable() - { - if (this.compatHookImpl != null) - this.compatHookImpl.Disable(); - else - throw new NotImplementedException(); - } + public virtual void Disable() => throw new NotImplementedException(); /// /// Check if this object has been disposed already. From 2bdc4445d469a081ef03ecec1267c2be3736ee98 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 4 Aug 2023 22:43:01 +0200 Subject: [PATCH 027/120] more warnings --- .../Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs | 1 + .../Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs | 1 + Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs | 1 + .../Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs | 1 + Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs | 1 + .../Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs | 1 + .../Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs | 1 + .../Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs | 1 + Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs | 1 + Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs | 1 + Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs | 1 + 11 files changed, 11 insertions(+) diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs index b998fea08..a4e98af79 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; + using Dalamud.Game; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs index 2680b29cc..7e4677fca 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AtkArrayDataBrowserWidget.cs @@ -1,4 +1,5 @@ using System.Numerics; + using Dalamud.Memory; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs index 699938e98..813e17c97 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FlyTextWidget.cs @@ -1,4 +1,5 @@ using System.Numerics; + using Dalamud.Game.Gui.FlyText; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs index 87744c809..52006419b 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; + using Dalamud.Interface.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs index b70883c36..141107a76 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/HookWidget.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; + using Dalamud.Hooking; using ImGuiNET; using PInvoke; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs index e37423c33..cb74462e0 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text.RegularExpressions; + using Dalamud.Data; using Dalamud.Game.Network; using Dalamud.Interface.Utility; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs index f5dfbb51b..cedadb455 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ObjectTableWidget.cs @@ -1,4 +1,5 @@ using System.Numerics; + using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.Gui; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs index de9d8dc4f..a8fdc428d 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TaskSchedulerWidget.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; + using Dalamud.Game; using Dalamud.Interface.Colors; using Dalamud.Interface.Utility; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs index a42351f1a..44d4164d1 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Numerics; + using Dalamud.Interface.Utility; using Dalamud.Plugin.Services; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs index 7b147da29..c7eab6e8c 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ToastWidget.cs @@ -1,4 +1,5 @@ using System.Numerics; + using Dalamud.Game.Gui.Toast; using Dalamud.Interface.Utility; using ImGuiNET; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs index 2f281538a..4f8af514a 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/UIColorWidget.cs @@ -1,4 +1,5 @@ using System.Numerics; + using Dalamud.Data; using ImGuiNET; using Lumina.Excel.GeneratedSheets; From b96ef30c20446d2a6f4a87ee57be4e61957815f7 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 5 Aug 2023 21:36:40 +0200 Subject: [PATCH 028/120] fix: ITextureProvider thread-safety --- Dalamud/Interface/Internal/TextureManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 983ae9963..1648f1961 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -1,4 +1,4 @@ -using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -485,17 +485,17 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -internal class TextureManagerPluginScoped : ITextureProvider, IServiceType, IDisposable +internal class TextureProviderPluginScoped : ITextureProvider, IServiceType, IDisposable { private readonly TextureManager textureManager; - private readonly List trackedTextures = new(); + private readonly ConcurrentBag trackedTextures = new(); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// TextureManager instance. - public TextureManagerPluginScoped(TextureManager textureManager) + public TextureProviderPluginScoped(TextureManager textureManager) { this.textureManager = textureManager; } From e1da238cb580fb030933ced4fb1a4a7e7c2d33a9 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 6 Aug 2023 20:58:55 +0200 Subject: [PATCH 029/120] feat: IHookProvider service, no more static hook creation --- Dalamud/Hooking/Hook.cs | 54 +++++----- Dalamud/Hooking/IDalamudHook.cs | 2 +- .../Internal/HookProviderPluginScoped.cs | 99 +++++++++++++++++++ Dalamud/Plugin/Services/IHookProvider.cs | 97 ++++++++++++++++++ Dalamud/Utility/Signatures/SignatureHelper.cs | 20 ++-- 5 files changed, 238 insertions(+), 34 deletions(-) create mode 100644 Dalamud/Hooking/Internal/HookProviderPluginScoped.cs create mode 100644 Dalamud/Plugin/Services/IHookProvider.cs diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs index 2e785191c..da65fedc7 100644 --- a/Dalamud/Hooking/Hook.cs +++ b/Dalamud/Hooking/Hook.cs @@ -12,7 +12,7 @@ namespace Dalamud.Hooking; /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. /// /// Delegate type to represents a function prototype. This must be the same prototype as original function do. -public abstract class Hook : IDisposable, IDalamudHook where T : Delegate +public abstract class Hook : IDalamudHook where T : Delegate { #pragma warning disable SA1310 // ReSharper disable once InconsistentNaming @@ -70,6 +70,27 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate /// public virtual string BackendName => throw new NotImplementedException(); + + /// + /// Remove a hook from the current process. + /// + public virtual void Dispose() + { + if (this.IsDisposed) + return; + + this.IsDisposed = true; + } + + /// + /// Starts intercepting a call to the function. + /// + public virtual void Enable() => throw new NotImplementedException(); + + /// + /// Stops intercepting a call to the function. + /// + public virtual void Disable() => throw new NotImplementedException(); /// /// Creates a hook by rewriting import table address. @@ -77,7 +98,7 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate /// A memory address to install a hook. /// Callback function. Delegate must have a same original function prototype. /// The hook with the supplied parameters. - public static unsafe Hook FromFunctionPointerVariable(IntPtr address, T detour) + internal static Hook FromFunctionPointerVariable(IntPtr address, T detour) { return new FunctionPointerVariableHook(address, detour, Assembly.GetCallingAssembly()); } @@ -91,7 +112,7 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate /// Hint or ordinal. 0 to unspecify. /// Callback function. Delegate must have a same original function prototype. /// The hook with the supplied parameters. - public static unsafe Hook FromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) + internal static unsafe Hook FromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) { module ??= Process.GetCurrentProcess().MainModule; if (module == null) @@ -156,7 +177,7 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate /// A name of the exported function name (e.g. send). /// Callback function. Delegate must have a same original function prototype. /// The hook with the supplied parameters. - public static Hook FromSymbol(string moduleName, string exportName, T detour) + internal static Hook FromSymbol(string moduleName, string exportName, T detour) => FromSymbol(moduleName, exportName, detour, false); /// @@ -169,7 +190,7 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate /// Callback function. Delegate must have a same original function prototype. /// Use the MinHook hooking library instead of Reloaded. /// The hook with the supplied parameters. - public static Hook FromSymbol(string moduleName, string exportName, T detour, bool useMinHook) + internal static Hook FromSymbol(string moduleName, string exportName, T detour, bool useMinHook) { if (EnvironmentConfiguration.DalamudForceMinHook) useMinHook = true; @@ -198,7 +219,7 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate /// Callback function. Delegate must have a same original function prototype. /// Use the MinHook hooking library instead of Reloaded. /// The hook with the supplied parameters. - public static Hook FromAddress(IntPtr procAddress, T detour, bool useMinHook = false) + internal static Hook FromAddress(IntPtr procAddress, T detour, bool useMinHook = false) { if (EnvironmentConfiguration.DalamudForceMinHook) useMinHook = true; @@ -210,27 +231,6 @@ public abstract class Hook : IDisposable, IDalamudHook where T : Delegate return new ReloadedHook(procAddress, detour, Assembly.GetCallingAssembly()); } - /// - /// Remove a hook from the current process. - /// - public virtual void Dispose() - { - if (this.IsDisposed) - return; - - this.IsDisposed = true; - } - - /// - /// Starts intercepting a call to the function. - /// - public virtual void Enable() => throw new NotImplementedException(); - - /// - /// Stops intercepting a call to the function. - /// - public virtual void Disable() => throw new NotImplementedException(); - /// /// Check if this object has been disposed already. /// diff --git a/Dalamud/Hooking/IDalamudHook.cs b/Dalamud/Hooking/IDalamudHook.cs index 1104597a1..bd7084d86 100644 --- a/Dalamud/Hooking/IDalamudHook.cs +++ b/Dalamud/Hooking/IDalamudHook.cs @@ -5,7 +5,7 @@ namespace Dalamud.Hooking; /// /// Interface describing a generic hook. /// -public interface IDalamudHook +public interface IDalamudHook : IDisposable { /// /// Gets the address to hook. diff --git a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs new file mode 100644 index 000000000..fa4497799 --- /dev/null +++ b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs @@ -0,0 +1,99 @@ +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Linq; + +using Dalamud.Game; +using Dalamud.IoC; +using Dalamud.IoC.Internal; +using Dalamud.Plugin.Internal.Types; +using Dalamud.Plugin.Services; +using Dalamud.Utility.Signatures; +using Serilog; + +namespace Dalamud.Hooking.Internal; + +/// +/// Plugin-scoped version of a texture manager. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposable +{ + private readonly LocalPlugin plugin; + private readonly SigScanner scanner; + + private readonly ConcurrentBag trackedHooks = new(); + + /// + /// Initializes a new instance of the class. + /// + /// Plugin this instance belongs to. + /// SigScanner instance for target module. + public HookProviderPluginScoped(LocalPlugin plugin, SigScanner scanner) + { + this.plugin = plugin; + this.scanner = scanner; + } + + /// + public void InitializeFromAttributes(object self) + { + foreach (var hook in SignatureHelper.Initialise(self)) + this.trackedHooks.Add(hook); + } + + /// + public Hook FromFunctionPointerVariable(IntPtr address, T detour) where T : Delegate + { + var hook = Hook.FromFunctionPointerVariable(address, detour); + this.trackedHooks.Add(hook); + return hook; + } + + /// + public Hook FromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) where T : Delegate + { + var hook = Hook.FromImport(module, moduleName, functionName, hintOrOrdinal, detour); + this.trackedHooks.Add(hook); + return hook; + } + + /// + public Hook FromSymbol(string moduleName, string exportName, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate + { + var hook = Hook.FromSymbol(moduleName, exportName, detour, backend == IHookProvider.HookBackend.MinHook); + this.trackedHooks.Add(hook); + return hook; + } + + /// + public Hook FromAddress(IntPtr procAddress, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate + { + var hook = Hook.FromAddress(procAddress, detour, backend == IHookProvider.HookBackend.MinHook); + this.trackedHooks.Add(hook); + return hook; + } + + /// + public Hook FromSignature(string signature, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate + => this.FromAddress(this.scanner.ScanText(signature), detour); + + /// + public void Dispose() + { + var notDisposed = this.trackedHooks.Where(x => !x.IsDisposed).ToArray(); + if (notDisposed.Length != 0) + Log.Warning("{PluginName} is leaking {Num} hooks! Make sure that all of them are disposed properly.", this.plugin.InternalName, notDisposed.Length); + + foreach (var hook in notDisposed) + { + hook.Dispose(); + } + + this.trackedHooks.Clear(); + } +} diff --git a/Dalamud/Plugin/Services/IHookProvider.cs b/Dalamud/Plugin/Services/IHookProvider.cs new file mode 100644 index 000000000..dc7d29913 --- /dev/null +++ b/Dalamud/Plugin/Services/IHookProvider.cs @@ -0,0 +1,97 @@ +using System.Diagnostics; + +using Dalamud.Hooking; +using Dalamud.Utility.Signatures; + +namespace Dalamud.Plugin.Services; + +/// +/// Service responsible for the creation of hooks. +/// +public interface IHookProvider +{ + /// + /// Available hooking backends. + /// + public enum HookBackend + { + /// + /// Choose the best backend automatically. + /// + Automatic, + + /// + /// Use Reloaded hooks. + /// + Reloaded, + + /// + /// Use MinHook. + /// You should never have to use this without talking to us first. + /// + MinHook, + } + + /// + /// Initialize members decorated with the . + /// Errors for fallible signatures will be logged. + /// + /// The object to initialise. + public void InitializeFromAttributes(object self); + + /// + /// Creates a hook by rewriting import table address. + /// + /// A memory address to install a hook. + /// Callback function. Delegate must have a same original function prototype. + /// The hook with the supplied parameters. + /// Delegate of detour. + public Hook FromFunctionPointerVariable(IntPtr address, T detour) where T : Delegate; + + /// + /// Creates a hook by rewriting import table address. + /// + /// Module to check for. Current process' main module if null. + /// Name of the DLL, including the extension. + /// Decorated name of the function. + /// Hint or ordinal. 0 to unspecify. + /// Callback function. Delegate must have a same original function prototype. + /// The hook with the supplied parameters. + /// Delegate of detour. + public Hook FromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) where T : Delegate; + + /// + /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. + /// The hook is not activated until Enable() method is called. + /// Please do not use MinHook unless you have thoroughly troubleshot why Reloaded does not work. + /// + /// A name of the module currently loaded in the memory. (e.g. ws2_32.dll). + /// A name of the exported function name (e.g. send). + /// Callback function. Delegate must have a same original function prototype. + /// Hooking library to use. + /// The hook with the supplied parameters. + /// Delegate of detour. + Hook FromSymbol(string moduleName, string exportName, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; + + /// + /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. + /// The hook is not activated until Enable() method is called. + /// Please do not use MinHook unless you have thoroughly troubleshot why Reloaded does not work. + /// + /// A memory address to install a hook. + /// Callback function. Delegate must have a same original function prototype. + /// Hooking library to use. + /// The hook with the supplied parameters. + /// Delegate of detour. + Hook FromAddress(IntPtr procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; + + /// + /// Creates a hook from a signature into the Dalamud target module. + /// + /// Signature of function to hook. + /// Callback function. Delegate must have a same original function prototype. + /// Hooking library to use. + /// The hook with the supplied parameters. + /// Delegate of detour. + Hook FromSignature(string signature, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; +} diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index bd99b8515..e133e5453 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -6,6 +7,7 @@ using System.Runtime.InteropServices; using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Logging; +using Dalamud.Plugin.Services; using Dalamud.Utility.Signatures.Wrappers; using Serilog; @@ -14,7 +16,7 @@ namespace Dalamud.Utility.Signatures; /// /// A utility class to help reduce signature boilerplate code. /// -public static class SignatureHelper +internal static class SignatureHelper { private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; @@ -24,7 +26,8 @@ public static class SignatureHelper /// /// The object to initialise. /// If warnings should be logged using . - public static void Initialise(object self, bool log = true) + /// Collection of created IDalamudHooks. + internal static IEnumerable Initialise(object self, bool log = true) { var scanner = Service.Get(); var selfType = self.GetType(); @@ -33,6 +36,8 @@ public static class SignatureHelper .Select(field => (field, field.GetCustomAttribute())) .Where(field => field.Item2 != null); + var createdHooks = new List(); + foreach (var (info, sig) in fields) { var wasWrapped = false; @@ -149,15 +154,16 @@ public static class SignatureHelper detour = del; } - var ctor = actualType.GetConstructor(new[] { typeof(IntPtr), hookDelegateType }); - if (ctor == null) + var creator = actualType.GetMethod("FromAddress", BindingFlags.Static | BindingFlags.NonPublic); + if (creator == null) { - Log.Error("Error in SignatureHelper: could not find Hook constructor"); + Log.Error("Error in SignatureHelper: could not find Hook creator"); continue; } - var hook = ctor.Invoke(new object?[] { ptr, detour }); + var hook = creator.Invoke(null, new object?[] { ptr, detour, IHookProvider.HookBackend.Automatic }) as IDalamudHook; info.SetValue(self, hook); + createdHooks.Add(hook); break; } @@ -182,5 +188,7 @@ public static class SignatureHelper } } } + + return createdHooks; } } From fe8ee19175df57334dd2e5aaea4899ea078c3a95 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 6 Aug 2023 21:08:49 +0200 Subject: [PATCH 030/120] fix comment --- Dalamud/Hooking/Internal/HookProviderPluginScoped.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs index fa4497799..0e7ef4c7b 100644 --- a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs +++ b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs @@ -13,7 +13,7 @@ using Serilog; namespace Dalamud.Hooking.Internal; /// -/// Plugin-scoped version of a texture manager. +/// Plugin-scoped version of service used to create hooks. /// [PluginInterface] [InterfaceVersion("1.0")] From 3f764d2e400bd585798f7e4ee58f6d4790573575 Mon Sep 17 00:00:00 2001 From: goat Date: Mon, 7 Aug 2023 23:57:31 +0200 Subject: [PATCH 031/120] pass on backend, spelling --- Dalamud/Hooking/Internal/HookProviderPluginScoped.cs | 4 ++-- Dalamud/Utility/Signatures/SignatureHelper.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs index 0e7ef4c7b..6fa700cef 100644 --- a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs +++ b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs @@ -42,7 +42,7 @@ internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposab /// public void InitializeFromAttributes(object self) { - foreach (var hook in SignatureHelper.Initialise(self)) + foreach (var hook in SignatureHelper.Initialize(self)) this.trackedHooks.Add(hook); } @@ -80,7 +80,7 @@ internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposab /// public Hook FromSignature(string signature, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate - => this.FromAddress(this.scanner.ScanText(signature), detour); + => this.FromAddress(this.scanner.ScanText(signature), detour, backend); /// public void Dispose() diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index e133e5453..1cfd18330 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -27,7 +27,7 @@ internal static class SignatureHelper /// The object to initialise. /// If warnings should be logged using . /// Collection of created IDalamudHooks. - internal static IEnumerable Initialise(object self, bool log = true) + internal static IEnumerable Initialize(object self, bool log = true) { var scanner = Service.Get(); var selfType = self.GetType(); From a6ed6dabe4206b445cad9b0f16d53633287c3bdf Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Thu, 10 Aug 2023 02:10:45 +0200 Subject: [PATCH 032/120] refactor: use IEnumerable instead of List in SeString.Append --- Dalamud/Game/Text/SeStringHandling/SeString.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index 2ddb73f12..6132d0910 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -421,7 +421,7 @@ public class SeString /// /// The Payloads to append. /// This object. - public SeString Append(List payloads) + public SeString Append(IEnumerable payloads) { this.Payloads.AddRange(payloads); return this; From 54790711ddcd6604f108f31fbd93fd4c3ec15240 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Thu, 10 Aug 2023 02:11:59 +0200 Subject: [PATCH 033/120] refactor: append payload list directly in SeStringBuilder --- Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs index 1fda9f9ae..dae9e11a9 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeStringBuilder.cs @@ -38,7 +38,11 @@ public class SeStringBuilder /// /// A list of payloads. /// The current builder. - public SeStringBuilder Append(IEnumerable payloads) => this.Append(new SeString(payloads.ToList())); + public SeStringBuilder Append(IEnumerable payloads) + { + this.BuiltString.Payloads.AddRange(payloads); + return this; + } /// /// Append raw text to the builder. From 342e1bc06c60b82bd077519058612eefa754dec3 Mon Sep 17 00:00:00 2001 From: srkizer Date: Tue, 29 Aug 2023 10:04:29 +0900 Subject: [PATCH 034/120] Make TextureManager.GetTexture return value non-nullable (#1342) --- Dalamud/Interface/Internal/TextureManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 1648f1961..b9efb42f3 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -203,7 +203,9 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP /// /// The texture to obtain a handle to. /// A texture wrap that can be used to render the texture. - public IDalamudTextureWrap? GetTexture(TexFile file) + /// Thrown when the graphics system is not available yet. Relevant for plugins when LoadRequiredState is set to 0 or 1. + /// Thrown when the given is not supported. Most likely is that the file is corrupt. + public IDalamudTextureWrap GetTexture(TexFile file) { ArgumentNullException.ThrowIfNull(file); From 385c4b7a8b01b01514a1e47042d58d752f1ab147 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:19:44 -0700 Subject: [PATCH 035/120] Add IFramework (#1286) --- Dalamud/Game/Framework.cs | 106 ++++-------------- Dalamud/Plugin/Services/IFramework.cs | 126 ++++++++++++++++++++++ Dalamud/Utility/EventHandlerExtensions.cs | 5 +- 3 files changed, 150 insertions(+), 87 deletions(-) create mode 100644 Dalamud/Plugin/Services/IFramework.cs diff --git a/Dalamud/Game/Framework.cs b/Dalamud/Game/Framework.cs index b3083e913..2b77bf400 100644 --- a/Dalamud/Game/Framework.cs +++ b/Dalamud/Game/Framework.cs @@ -12,6 +12,7 @@ using Dalamud.Game.Gui.Toast; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using Dalamud.Utility; using Serilog; @@ -23,7 +24,10 @@ namespace Dalamud.Game; [PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed class Framework : IDisposable, IServiceType +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +public sealed class Framework : IDisposable, IServiceType, IFramework { private static readonly Stopwatch StatsStopwatch = new(); @@ -57,12 +61,6 @@ public sealed class Framework : IDisposable, IServiceType this.destroyHook = Hook.FromAddress(this.Address.DestroyAddress, this.HandleFrameworkDestroy); } - /// - /// A delegate type used with the event. - /// - /// The Framework instance. - public delegate void OnUpdateDelegate(Framework framework); - /// /// A delegate type used during the native Framework::destroy. /// @@ -81,10 +79,8 @@ public sealed class Framework : IDisposable, IServiceType private delegate IntPtr OnDestroyDetour(); // OnDestroyDelegate - /// - /// Event that gets fired every time the game framework updates. - /// - public event OnUpdateDelegate Update; + /// + public event IFramework.OnUpdateDelegate Update; /// /// Gets or sets a value indicating whether the collection of stats is enabled. @@ -96,34 +92,22 @@ public sealed class Framework : IDisposable, IServiceType /// public static Dictionary> StatsHistory { get; } = new(); - /// - /// Gets a raw pointer to the instance of Client::Framework. - /// + /// public FrameworkAddressResolver Address { get; } - /// - /// Gets the last time that the Framework Update event was triggered. - /// + /// public DateTime LastUpdate { get; private set; } = DateTime.MinValue; - /// - /// Gets the last time in UTC that the Framework Update event was triggered. - /// + /// public DateTime LastUpdateUTC { get; private set; } = DateTime.MinValue; - /// - /// Gets the delta between the last Framework Update and the currently executing one. - /// + /// public TimeSpan UpdateDelta { get; private set; } = TimeSpan.Zero; - /// - /// Gets a value indicating whether currently executing code is running in the game's framework update thread. - /// + /// public bool IsInFrameworkUpdateThread => Thread.CurrentThread == this.frameworkUpdateThread; - /// - /// Gets a value indicating whether game Framework is unloading. - /// + /// public bool IsFrameworkUnloading { get; internal set; } /// @@ -131,20 +115,11 @@ public sealed class Framework : IDisposable, IServiceType /// internal bool DispatchUpdateEvents { get; set; } = true; - /// - /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. - /// - /// Return type. - /// Function to call. - /// Task representing the pending or already completed function. + /// public Task RunOnFrameworkThread(Func func) => this.IsInFrameworkUpdateThread || this.IsFrameworkUnloading ? Task.FromResult(func()) : this.RunOnTick(func); - /// - /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. - /// - /// Function to call. - /// Task representing the pending or already completed function. + /// public Task RunOnFrameworkThread(Action action) { if (this.IsInFrameworkUpdateThread || this.IsFrameworkUnloading) @@ -165,32 +140,15 @@ public sealed class Framework : IDisposable, IServiceType } } - /// - /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. - /// - /// Return type. - /// Function to call. - /// Task representing the pending or already completed function. + /// public Task RunOnFrameworkThread(Func> func) => this.IsInFrameworkUpdateThread || this.IsFrameworkUnloading ? func() : this.RunOnTick(func); - /// - /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. - /// - /// Function to call. - /// Task representing the pending or already completed function. + /// public Task RunOnFrameworkThread(Func func) => this.IsInFrameworkUpdateThread || this.IsFrameworkUnloading ? func() : this.RunOnTick(func); - /// - /// Run given function in upcoming Framework.Tick call. - /// - /// Return type. - /// Function to call. - /// Wait for given timespan before calling this function. - /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. - /// Cancellation token which will prevent the execution of this function if wait conditions are not met. - /// Task representing the pending function. + /// public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) { if (this.IsFrameworkUnloading) @@ -219,14 +177,7 @@ public sealed class Framework : IDisposable, IServiceType return tcs.Task; } - /// - /// Run given function in upcoming Framework.Tick call. - /// - /// Function to call. - /// Wait for given timespan before calling this function. - /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. - /// Cancellation token which will prevent the execution of this function if wait conditions are not met. - /// Task representing the pending function. + /// public Task RunOnTick(Action action, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) { if (this.IsFrameworkUnloading) @@ -255,15 +206,7 @@ public sealed class Framework : IDisposable, IServiceType return tcs.Task; } - /// - /// Run given function in upcoming Framework.Tick call. - /// - /// Return type. - /// Function to call. - /// Wait for given timespan before calling this function. - /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. - /// Cancellation token which will prevent the execution of this function if wait conditions are not met. - /// Task representing the pending function. + /// public Task RunOnTick(Func> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) { if (this.IsFrameworkUnloading) @@ -292,14 +235,7 @@ public sealed class Framework : IDisposable, IServiceType return tcs.Task.ContinueWith(x => x.Result, cancellationToken).Unwrap(); } - /// - /// Run given function in upcoming Framework.Tick call. - /// - /// Function to call. - /// Wait for given timespan before calling this function. - /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. - /// Cancellation token which will prevent the execution of this function if wait conditions are not met. - /// Task representing the pending function. + /// public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) { if (this.IsFrameworkUnloading) diff --git a/Dalamud/Plugin/Services/IFramework.cs b/Dalamud/Plugin/Services/IFramework.cs new file mode 100644 index 000000000..69c21bca4 --- /dev/null +++ b/Dalamud/Plugin/Services/IFramework.cs @@ -0,0 +1,126 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +using Dalamud.Game; + +namespace Dalamud.Plugin.Services; + +/// +/// This class represents the Framework of the native game client and grants access to various subsystems. +/// +public interface IFramework +{ + /// + /// A delegate type used with the event. + /// + /// The Framework instance. + public delegate void OnUpdateDelegate(Framework framework); + + /// + /// Event that gets fired every time the game framework updates. + /// + public event OnUpdateDelegate Update; + + /// + /// Gets a raw pointer to the instance of Client::Framework. + /// + public FrameworkAddressResolver Address { get; } + + /// + /// Gets the last time that the Framework Update event was triggered. + /// + public DateTime LastUpdate { get; } + + /// + /// Gets the last time in UTC that the Framework Update event was triggered. + /// + public DateTime LastUpdateUTC { get; } + + /// + /// Gets the delta between the last Framework Update and the currently executing one. + /// + public TimeSpan UpdateDelta { get; } + + /// + /// Gets a value indicating whether currently executing code is running in the game's framework update thread. + /// + public bool IsInFrameworkUpdateThread { get; } + + /// + /// Gets a value indicating whether game Framework is unloading. + /// + public bool IsFrameworkUnloading { get; } + + /// + /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. + /// + /// Return type. + /// Function to call. + /// Task representing the pending or already completed function. + public Task RunOnFrameworkThread(Func func); + + /// + /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. + /// + /// Function to call. + /// Task representing the pending or already completed function. + public Task RunOnFrameworkThread(Action action); + + /// + /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. + /// + /// Return type. + /// Function to call. + /// Task representing the pending or already completed function. + public Task RunOnFrameworkThread(Func> func); + + /// + /// Run given function right away if this function has been called from game's Framework.Update thread, or otherwise run on next Framework.Update call. + /// + /// Function to call. + /// Task representing the pending or already completed function. + public Task RunOnFrameworkThread(Func func); + + /// + /// Run given function in upcoming Framework.Tick call. + /// + /// Return type. + /// Function to call. + /// Wait for given timespan before calling this function. + /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. + /// Cancellation token which will prevent the execution of this function if wait conditions are not met. + /// Task representing the pending function. + public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); + + /// + /// Run given function in upcoming Framework.Tick call. + /// + /// Function to call. + /// Wait for given timespan before calling this function. + /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. + /// Cancellation token which will prevent the execution of this function if wait conditions are not met. + /// Task representing the pending function. + public Task RunOnTick(Action action, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); + + /// + /// Run given function in upcoming Framework.Tick call. + /// + /// Return type. + /// Function to call. + /// Wait for given timespan before calling this function. + /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. + /// Cancellation token which will prevent the execution of this function if wait conditions are not met. + /// Task representing the pending function. + public Task RunOnTick(Func> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); + + /// + /// Run given function in upcoming Framework.Tick call. + /// + /// Function to call. + /// Wait for given timespan before calling this function. + /// Count given number of Framework.Tick calls before calling this function. This takes precedence over delay parameter. + /// Cancellation token which will prevent the execution of this function if wait conditions are not met. + /// Task representing the pending function. + public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default); +} diff --git a/Dalamud/Utility/EventHandlerExtensions.cs b/Dalamud/Utility/EventHandlerExtensions.cs index bce815a7b..eefd245bb 100644 --- a/Dalamud/Utility/EventHandlerExtensions.cs +++ b/Dalamud/Utility/EventHandlerExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using Dalamud.Game; +using Dalamud.Plugin.Services; using Serilog; using static Dalamud.Game.Framework; @@ -72,12 +73,12 @@ internal static class EventHandlerExtensions /// /// The OnUpdateDelegate in question. /// Framework to be passed on to OnUpdateDelegate. - public static void InvokeSafely(this OnUpdateDelegate updateDelegate, Framework framework) + public static void InvokeSafely(this IFramework.OnUpdateDelegate updateDelegate, Framework framework) { if (updateDelegate == null) return; - foreach (var action in updateDelegate.GetInvocationList().Cast()) + foreach (var action in updateDelegate.GetInvocationList().Cast()) { HandleInvoke(() => action(framework)); } From 275ec72ab769cfcbf85c09d2c693254219a3c8ad Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Sun, 10 Sep 2023 14:56:28 -0700 Subject: [PATCH 036/120] Re-Add Lost Import - No idea how, but the import for ImGuiHelpers was lost. --- Dalamud/Interface/Components/ImGuiComponents.IconButton.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs b/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs index 05e660b61..1c484d423 100644 --- a/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs +++ b/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs @@ -1,6 +1,7 @@ using System; using System.Numerics; +using Dalamud.Interface.Utility; using ImGuiNET; namespace Dalamud.Interface.Components; From d378fe1dfcb0255eaa03d0818d7025ce4cbaeb26 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sun, 10 Sep 2023 15:20:44 -0700 Subject: [PATCH 037/120] Add IPartyFinderGui (v9) (#1279) --- .../Game/Gui/PartyFinder/PartyFinderGui.cs | 52 +++++++++++++------ Dalamud/Plugin/Services/IPartyFinderGui.cs | 23 ++++++++ 2 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 Dalamud/Plugin/Services/IPartyFinderGui.cs diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs index 6427f2a54..85c6a4a39 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs @@ -6,6 +6,7 @@ using Dalamud.Game.Gui.PartyFinder.Types; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using Serilog; namespace Dalamud.Game.Gui.PartyFinder; @@ -13,10 +14,9 @@ namespace Dalamud.Game.Gui.PartyFinder; /// /// This class handles interacting with the native PartyFinder window. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed class PartyFinderGui : IDisposable, IServiceType +internal sealed class PartyFinderGui : IDisposable, IServiceType, IPartyFinderGui { private readonly PartyFinderAddressResolver address; private readonly IntPtr memory; @@ -35,25 +35,14 @@ public sealed class PartyFinderGui : IDisposable, IServiceType this.memory = Marshal.AllocHGlobal(PartyFinderPacket.PacketSize); - this.receiveListingHook = Hook.FromAddress(this.address.ReceiveListing, new ReceiveListingDelegate(this.HandleReceiveListingDetour)); + this.receiveListingHook = Hook.FromAddress(this.address.ReceiveListing, this.HandleReceiveListingDetour); } - /// - /// Event type fired each time the game receives an individual Party Finder listing. - /// Cannot modify listings but can hide them. - /// - /// The listings received. - /// Additional arguments passed by the game. - public delegate void PartyFinderListingEventDelegate(PartyFinderListing listing, PartyFinderListingEventArgs args); - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate void ReceiveListingDelegate(IntPtr managerPtr, IntPtr data); - /// - /// Event fired each time the game receives an individual Party Finder listing. - /// Cannot modify listings but can hide them. - /// - public event PartyFinderListingEventDelegate ReceiveListing; + /// + public event IPartyFinderGui.PartyFinderListingEventDelegate? ReceiveListing; /// /// Dispose of managed and unmanaged resources. @@ -138,3 +127,34 @@ public sealed class PartyFinderGui : IDisposable, IServiceType } } } + +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class PartyFinderGuiPluginScoped : IDisposable, IServiceType, IPartyFinderGui +{ + [ServiceManager.ServiceDependency] + private readonly PartyFinderGui partyFinderGuiService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal PartyFinderGuiPluginScoped() + { + this.partyFinderGuiService.ReceiveListing += this.ReceiveListingForward; + } + + /// + public event IPartyFinderGui.PartyFinderListingEventDelegate? ReceiveListing; + + /// + public void Dispose() + { + this.partyFinderGuiService.ReceiveListing -= this.ReceiveListingForward; + } + + private void ReceiveListingForward(PartyFinderListing listing, PartyFinderListingEventArgs args) => this.ReceiveListing?.Invoke(listing, args); +} diff --git a/Dalamud/Plugin/Services/IPartyFinderGui.cs b/Dalamud/Plugin/Services/IPartyFinderGui.cs new file mode 100644 index 000000000..f656963db --- /dev/null +++ b/Dalamud/Plugin/Services/IPartyFinderGui.cs @@ -0,0 +1,23 @@ +using Dalamud.Game.Gui.PartyFinder.Types; + +namespace Dalamud.Plugin.Services; + +/// +/// This class handles interacting with the native PartyFinder window. +/// +public interface IPartyFinderGui +{ + /// + /// Event type fired each time the game receives an individual Party Finder listing. + /// Cannot modify listings but can hide them. + /// + /// The listings received. + /// Additional arguments passed by the game. + public delegate void PartyFinderListingEventDelegate(PartyFinderListing listing, PartyFinderListingEventArgs args); + + /// + /// Event fired each time the game receives an individual Party Finder listing. + /// Cannot modify listings but can hide them. + /// + public event PartyFinderListingEventDelegate ReceiveListing; +} From 617c2bdb9c752ee067eacbabf5827dc2731b06e5 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sun, 10 Sep 2023 16:18:10 -0700 Subject: [PATCH 038/120] Add IFlyTextGui (v9) (#1278) --- Dalamud/Game/Gui/FlyText/FlyTextGui.cs | 92 +++++++++++++------------- Dalamud/Plugin/Services/IFlyTextGui.cs | 55 +++++++++++++++ 2 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 Dalamud/Plugin/Services/IFlyTextGui.cs diff --git a/Dalamud/Game/Gui/FlyText/FlyTextGui.cs b/Dalamud/Game/Gui/FlyText/FlyTextGui.cs index f2222a7cd..3c04c744a 100644 --- a/Dalamud/Game/Gui/FlyText/FlyTextGui.cs +++ b/Dalamud/Game/Gui/FlyText/FlyTextGui.cs @@ -7,6 +7,7 @@ using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Memory; +using Dalamud.Plugin.Services; using Serilog; namespace Dalamud.Game.Gui.FlyText; @@ -14,10 +15,9 @@ namespace Dalamud.Game.Gui.FlyText; /// /// This class facilitates interacting with and creating native in-game "fly text". /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed class FlyTextGui : IDisposable, IServiceType +internal sealed class FlyTextGui : IDisposable, IServiceType, IFlyTextGui { /// /// The native function responsible for adding fly text to the UI. See . @@ -39,32 +39,6 @@ public sealed class FlyTextGui : IDisposable, IServiceType this.createFlyTextHook = Hook.FromAddress(this.Address.CreateFlyText, this.CreateFlyTextDetour); } - /// - /// The delegate defining the type for the FlyText event. - /// - /// The FlyTextKind. See . - /// Value1 passed to the native flytext function. - /// Value2 passed to the native flytext function. Seems unused. - /// Text1 passed to the native flytext function. - /// Text2 passed to the native flytext function. - /// Color passed to the native flytext function. Changes flytext color. - /// Icon ID passed to the native flytext function. Only displays with select FlyTextKind. - /// Damage Type Icon ID passed to the native flytext function. Displayed next to damage values to denote damage type. - /// The vertical offset to place the flytext at. 0 is default. Negative values result - /// in text appearing higher on the screen. This does not change where the element begins to fade. - /// Whether this flytext has been handled. If a subscriber sets this to true, the FlyText will not appear. - public delegate void OnFlyTextCreatedDelegate( - ref FlyTextKind kind, - ref int val1, - ref int val2, - ref SeString text1, - ref SeString text2, - ref uint color, - ref uint icon, - ref uint damageTypeIcon, - ref float yOffset, - ref bool handled); - /// /// Private delegate for the native CreateFlyText function's hook. /// @@ -95,12 +69,8 @@ public sealed class FlyTextGui : IDisposable, IServiceType uint offsetStrMax, int unknown); - /// - /// The FlyText event that can be subscribed to. - /// - public event OnFlyTextCreatedDelegate? FlyTextCreated; - - private Dalamud Dalamud { get; } + /// + public event IFlyTextGui.OnFlyTextCreatedDelegate? FlyTextCreated; private FlyTextGuiAddressResolver Address { get; } @@ -112,18 +82,7 @@ public sealed class FlyTextGui : IDisposable, IServiceType this.createFlyTextHook.Dispose(); } - /// - /// Displays a fly text in-game on the local player. - /// - /// The FlyTextKind. See . - /// The index of the actor to place flytext on. Indexing unknown. 1 places flytext on local player. - /// Value1 passed to the native flytext function. - /// Value2 passed to the native flytext function. Seems unused. - /// Text1 passed to the native flytext function. - /// Text2 passed to the native flytext function. - /// Color passed to the native flytext function. Changes flytext color. - /// Icon ID passed to the native flytext function. Only displays with select FlyTextKind. - /// Damage Type Icon ID passed to the native flytext function. Displayed next to damage values to denote damage type. + /// public unsafe void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon, uint damageTypeIcon) { // Known valid flytext region within the atk arrays @@ -318,3 +277,44 @@ public sealed class FlyTextGui : IDisposable, IServiceType return retVal; } } + +/// +/// Plugin scoped version of FlyTextGui. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class FlyTextGuiPluginScoped : IDisposable, IServiceType, IFlyTextGui +{ + [ServiceManager.ServiceDependency] + private readonly FlyTextGui flyTextGuiService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal FlyTextGuiPluginScoped() + { + this.flyTextGuiService.FlyTextCreated += this.FlyTextCreatedForward; + } + + /// + public event IFlyTextGui.OnFlyTextCreatedDelegate? FlyTextCreated; + + /// + public void Dispose() + { + this.flyTextGuiService.FlyTextCreated -= this.FlyTextCreatedForward; + } + + /// + public void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon, uint damageTypeIcon) + { + this.flyTextGuiService.AddFlyText(kind, actorIndex, val1, val2, text1, text2, color, icon, damageTypeIcon); + } + + private void FlyTextCreatedForward(ref FlyTextKind kind, ref int val1, ref int val2, ref SeString text1, ref SeString text2, ref uint color, ref uint icon, ref uint damageTypeIcon, ref float yOffset, ref bool handled) + => this.FlyTextCreated?.Invoke(ref kind, ref val1, ref val2, ref text1, ref text2, ref color, ref icon, ref damageTypeIcon, ref yOffset, ref handled); +} diff --git a/Dalamud/Plugin/Services/IFlyTextGui.cs b/Dalamud/Plugin/Services/IFlyTextGui.cs new file mode 100644 index 000000000..04fae351d --- /dev/null +++ b/Dalamud/Plugin/Services/IFlyTextGui.cs @@ -0,0 +1,55 @@ +using Dalamud.Game.Gui.FlyText; +using Dalamud.Game.Text.SeStringHandling; + +namespace Dalamud.Plugin.Services; + +/// +/// This class facilitates interacting with and creating native in-game "fly text". +/// +public interface IFlyTextGui +{ + /// + /// The delegate defining the type for the FlyText event. + /// + /// The FlyTextKind. See . + /// Value1 passed to the native flytext function. + /// Value2 passed to the native flytext function. Seems unused. + /// Text1 passed to the native flytext function. + /// Text2 passed to the native flytext function. + /// Color passed to the native flytext function. Changes flytext color. + /// Icon ID passed to the native flytext function. Only displays with select FlyTextKind. + /// Damage Type Icon ID passed to the native flytext function. Displayed next to damage values to denote damage type. + /// The vertical offset to place the flytext at. 0 is default. Negative values result + /// in text appearing higher on the screen. This does not change where the element begins to fade. + /// Whether this flytext has been handled. If a subscriber sets this to true, the FlyText will not appear. + public delegate void OnFlyTextCreatedDelegate( + ref FlyTextKind kind, + ref int val1, + ref int val2, + ref SeString text1, + ref SeString text2, + ref uint color, + ref uint icon, + ref uint damageTypeIcon, + ref float yOffset, + ref bool handled); + + /// + /// The FlyText event that can be subscribed to. + /// + public event OnFlyTextCreatedDelegate? FlyTextCreated; + + /// + /// Displays a fly text in-game on the local player. + /// + /// The FlyTextKind. See . + /// The index of the actor to place flytext on. Indexing unknown. 1 places flytext on local player. + /// Value1 passed to the native flytext function. + /// Value2 passed to the native flytext function. Seems unused. + /// Text1 passed to the native flytext function. + /// Text2 passed to the native flytext function. + /// Color passed to the native flytext function. Changes flytext color. + /// Icon ID passed to the native flytext function. Only displays with select FlyTextKind. + /// Damage Type Icon ID passed to the native flytext function. Displayed next to damage values to denote damage type. + public void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon, uint damageTypeIcon); +} From 0f3b9eab8cd52d0e42a269f3f4d32caefaca7824 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sun, 10 Sep 2023 16:24:47 -0700 Subject: [PATCH 039/120] Add IToastGui (v9) (#1280) --- Dalamud/Game/Gui/Toast/ToastGui.cs | 183 ++++++++++++++------------- Dalamud/Plugin/Services/IToastGui.cs | 88 +++++++++++++ 2 files changed, 186 insertions(+), 85 deletions(-) create mode 100644 Dalamud/Plugin/Services/IToastGui.cs diff --git a/Dalamud/Game/Gui/Toast/ToastGui.cs b/Dalamud/Game/Gui/Toast/ToastGui.cs index e65fa1444..93126710b 100644 --- a/Dalamud/Game/Gui/Toast/ToastGui.cs +++ b/Dalamud/Game/Gui/Toast/ToastGui.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; @@ -6,16 +5,16 @@ using Dalamud.Game.Text.SeStringHandling; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; namespace Dalamud.Game.Gui.Toast; /// /// This class facilitates interacting with and creating native toast windows. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed partial class ToastGui : IDisposable, IServiceType +internal sealed partial class ToastGui : IDisposable, IServiceType, IToastGui { private const uint QuestToastCheckmarkMagic = 60081; @@ -39,38 +38,11 @@ public sealed partial class ToastGui : IDisposable, IServiceType this.address = new ToastGuiAddressResolver(); this.address.Setup(sigScanner); - this.showNormalToastHook = Hook.FromAddress(this.address.ShowNormalToast, new ShowNormalToastDelegate(this.HandleNormalToastDetour)); - this.showQuestToastHook = Hook.FromAddress(this.address.ShowQuestToast, new ShowQuestToastDelegate(this.HandleQuestToastDetour)); - this.showErrorToastHook = Hook.FromAddress(this.address.ShowErrorToast, new ShowErrorToastDelegate(this.HandleErrorToastDetour)); + this.showNormalToastHook = Hook.FromAddress(this.address.ShowNormalToast, this.HandleNormalToastDetour); + this.showQuestToastHook = Hook.FromAddress(this.address.ShowQuestToast, this.HandleQuestToastDetour); + this.showErrorToastHook = Hook.FromAddress(this.address.ShowErrorToast, this.HandleErrorToastDetour); } - #region Event delegates - - /// - /// A delegate type used when a normal toast window appears. - /// - /// The message displayed. - /// Assorted toast options. - /// Whether the toast has been handled or should be propagated. - public delegate void OnNormalToastDelegate(ref SeString message, ref ToastOptions options, ref bool isHandled); - - /// - /// A delegate type used when a quest toast window appears. - /// - /// The message displayed. - /// Assorted toast options. - /// Whether the toast has been handled or should be propagated. - public delegate void OnQuestToastDelegate(ref SeString message, ref QuestToastOptions options, ref bool isHandled); - - /// - /// A delegate type used when an error toast window appears. - /// - /// The message displayed. - /// Whether the toast has been handled or should be propagated. - public delegate void OnErrorToastDelegate(ref SeString message, ref bool isHandled); - - #endregion - #region Marshal delegates private delegate IntPtr ShowNormalToastDelegate(IntPtr manager, IntPtr text, int layer, byte isTop, byte isFast, int logMessageId); @@ -82,21 +54,15 @@ public sealed partial class ToastGui : IDisposable, IServiceType #endregion #region Events + + /// + public event IToastGui.OnNormalToastDelegate? Toast; - /// - /// Event that will be fired when a toast is sent by the game or a plugin. - /// - public event OnNormalToastDelegate Toast; + /// + public event IToastGui.OnQuestToastDelegate? QuestToast; - /// - /// Event that will be fired when a quest toast is sent by the game or a plugin. - /// - public event OnQuestToastDelegate QuestToast; - - /// - /// Event that will be fired when an error toast is sent by the game or a plugin. - /// - public event OnErrorToastDelegate ErrorToast; + /// + public event IToastGui.OnErrorToastDelegate? ErrorToast; #endregion @@ -172,31 +138,23 @@ public sealed partial class ToastGui : IDisposable, IServiceType /// /// Handles normal toasts. /// -public sealed partial class ToastGui +internal sealed partial class ToastGui { - /// - /// Show a toast message with the given content. - /// - /// The message to be shown. - /// Options for the toast. - public void ShowNormal(string message, ToastOptions options = null) + /// + public void ShowNormal(string message, ToastOptions? options = null) { options ??= new ToastOptions(); this.normalQueue.Enqueue((Encoding.UTF8.GetBytes(message), options)); } - - /// - /// Show a toast message with the given content. - /// - /// The message to be shown. - /// Options for the toast. - public void ShowNormal(SeString message, ToastOptions options = null) + + /// + public void ShowNormal(SeString message, ToastOptions? options = null) { options ??= new ToastOptions(); this.normalQueue.Enqueue((message.Encode(), options)); } - private void ShowNormal(byte[] bytes, ToastOptions options = null) + private void ShowNormal(byte[] bytes, ToastOptions? options = null) { options ??= new ToastOptions(); @@ -255,31 +213,23 @@ public sealed partial class ToastGui /// /// Handles quest toasts. /// -public sealed partial class ToastGui +internal sealed partial class ToastGui { - /// - /// Show a quest toast message with the given content. - /// - /// The message to be shown. - /// Options for the toast. - public void ShowQuest(string message, QuestToastOptions options = null) + /// + public void ShowQuest(string message, QuestToastOptions? options = null) { options ??= new QuestToastOptions(); this.questQueue.Enqueue((Encoding.UTF8.GetBytes(message), options)); } - - /// - /// Show a quest toast message with the given content. - /// - /// The message to be shown. - /// Options for the toast. - public void ShowQuest(SeString message, QuestToastOptions options = null) + + /// + public void ShowQuest(SeString message, QuestToastOptions? options = null) { options ??= new QuestToastOptions(); this.questQueue.Enqueue((message.Encode(), options)); } - private void ShowQuest(byte[] bytes, QuestToastOptions options = null) + private void ShowQuest(byte[] bytes, QuestToastOptions? options = null) { options ??= new QuestToastOptions(); @@ -365,21 +315,15 @@ public sealed partial class ToastGui /// /// Handles error toasts. /// -public sealed partial class ToastGui +internal sealed partial class ToastGui { - /// - /// Show an error toast message with the given content. - /// - /// The message to be shown. + /// public void ShowError(string message) { this.errorQueue.Enqueue(Encoding.UTF8.GetBytes(message)); } - /// - /// Show an error toast message with the given content. - /// - /// The message to be shown. + /// public void ShowError(SeString message) { this.errorQueue.Enqueue(message.Encode()); @@ -433,3 +377,72 @@ public sealed partial class ToastGui } } } + +/// +/// Plugin scoped version of ToastGui. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class ToastGuiPluginScoped : IDisposable, IServiceType, IToastGui +{ + [ServiceManager.ServiceDependency] + private readonly ToastGui toastGuiService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal ToastGuiPluginScoped() + { + this.toastGuiService.Toast += this.ToastForward; + this.toastGuiService.QuestToast += this.QuestToastForward; + this.toastGuiService.ErrorToast += this.ErrorToastForward; + } + + /// + public event IToastGui.OnNormalToastDelegate? Toast; + + /// + public event IToastGui.OnQuestToastDelegate? QuestToast; + + /// + public event IToastGui.OnErrorToastDelegate? ErrorToast; + + /// + public void Dispose() + { + this.toastGuiService.Toast -= this.ToastForward; + this.toastGuiService.QuestToast -= this.QuestToastForward; + this.toastGuiService.ErrorToast -= this.ErrorToastForward; + } + + /// + public void ShowNormal(string message, ToastOptions? options = null) => this.toastGuiService.ShowNormal(message, options); + + /// + public void ShowNormal(SeString message, ToastOptions? options = null) => this.toastGuiService.ShowNormal(message, options); + + /// + public void ShowQuest(string message, QuestToastOptions? options = null) => this.toastGuiService.ShowQuest(message, options); + + /// + public void ShowQuest(SeString message, QuestToastOptions? options = null) => this.toastGuiService.ShowQuest(message, options); + + /// + public void ShowError(string message) => this.toastGuiService.ShowError(message); + + /// + public void ShowError(SeString message) => this.toastGuiService.ShowError(message); + + private void ToastForward(ref SeString message, ref ToastOptions options, ref bool isHandled) + => this.Toast?.Invoke(ref message, ref options, ref isHandled); + + private void QuestToastForward(ref SeString message, ref QuestToastOptions options, ref bool isHandled) + => this.QuestToast?.Invoke(ref message, ref options, ref isHandled); + + private void ErrorToastForward(ref SeString message, ref bool isHandled) + => this.ErrorToast?.Invoke(ref message, ref isHandled); +} diff --git a/Dalamud/Plugin/Services/IToastGui.cs b/Dalamud/Plugin/Services/IToastGui.cs new file mode 100644 index 000000000..ef83e95ac --- /dev/null +++ b/Dalamud/Plugin/Services/IToastGui.cs @@ -0,0 +1,88 @@ +using Dalamud.Game.Gui.Toast; +using Dalamud.Game.Text.SeStringHandling; + +namespace Dalamud.Plugin.Services; + +/// +/// This class facilitates interacting with and creating native toast windows. +/// +public interface IToastGui +{ + /// + /// A delegate type used when a normal toast window appears. + /// + /// The message displayed. + /// Assorted toast options. + /// Whether the toast has been handled or should be propagated. + public delegate void OnNormalToastDelegate(ref SeString message, ref ToastOptions options, ref bool isHandled); + + /// + /// A delegate type used when a quest toast window appears. + /// + /// The message displayed. + /// Assorted toast options. + /// Whether the toast has been handled or should be propagated. + public delegate void OnQuestToastDelegate(ref SeString message, ref QuestToastOptions options, ref bool isHandled); + + /// + /// A delegate type used when an error toast window appears. + /// + /// The message displayed. + /// Whether the toast has been handled or should be propagated. + public delegate void OnErrorToastDelegate(ref SeString message, ref bool isHandled); + + /// + /// Event that will be fired when a toast is sent by the game or a plugin. + /// + public event OnNormalToastDelegate Toast; + + /// + /// Event that will be fired when a quest toast is sent by the game or a plugin. + /// + public event OnQuestToastDelegate QuestToast; + + /// + /// Event that will be fired when an error toast is sent by the game or a plugin. + /// + public event OnErrorToastDelegate ErrorToast; + + /// + /// Show a toast message with the given content. + /// + /// The message to be shown. + /// Options for the toast. + public void ShowNormal(string message, ToastOptions? options = null); + + /// + /// Show a toast message with the given content. + /// + /// The message to be shown. + /// Options for the toast. + public void ShowNormal(SeString message, ToastOptions? options = null); + + /// + /// Show a quest toast message with the given content. + /// + /// The message to be shown. + /// Options for the toast. + public void ShowQuest(string message, QuestToastOptions? options = null); + + /// + /// Show a quest toast message with the given content. + /// + /// The message to be shown. + /// Options for the toast. + public void ShowQuest(SeString message, QuestToastOptions? options = null); + + /// + /// Show an error toast message with the given content. + /// + /// The message to be shown. + public void ShowError(string message); + + /// + /// Show an error toast message with the given content. + /// + /// The message to be shown. + public void ShowError(SeString message); +} From 4870428bac6c90bd498e11796f53c358967df551 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Mon, 11 Sep 2023 21:32:56 -0700 Subject: [PATCH 040/120] Bump Lumina to 3.11.0 --- Dalamud.CorePlugin/Dalamud.CorePlugin.csproj | 2 +- Dalamud/Dalamud.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj b/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj index 25919af07..3938d0c80 100644 --- a/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj +++ b/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj @@ -27,7 +27,7 @@ - + diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index b147dc961..98b515642 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -67,7 +67,7 @@ - + From af632175647debf7d469ba2f709ffe1e186e0e10 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:06:40 -0700 Subject: [PATCH 041/120] Add ITitleScreenMenu and Scoped Service. (#1379) --- .../Internal/Windows/TitleScreenMenuWindow.cs | 3 +- .../{ => TitleScreenMenu}/TitleScreenMenu.cs | 168 ++++++------------ .../TitleScreenMenu/TitleScreenMenuEntry.cs | 94 ++++++++++ Dalamud/Plugin/Services/ITitleScreenMenu.cs | 44 +++++ 4 files changed, 195 insertions(+), 114 deletions(-) rename Dalamud/Interface/{ => TitleScreenMenu}/TitleScreenMenu.cs (50%) create mode 100644 Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs create mode 100644 Dalamud/Plugin/Services/ITitleScreenMenu.cs diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index e92c80846..e3cf78296 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -230,7 +229,7 @@ internal class TitleScreenMenuWindow : Window, IDisposable } private bool DrawEntry( - TitleScreenMenu.TitleScreenMenuEntry entry, bool inhibitFadeout, bool showText, bool isFirst, bool overrideAlpha, bool interactable) + TitleScreenMenuEntry entry, bool inhibitFadeout, bool showText, bool isFirst, bool overrideAlpha, bool interactable) { InterfaceManager.SpecialGlyphRequest fontHandle; if (this.specialGlyphRequests.TryGetValue(entry.Name, out fontHandle) && fontHandle.Size != TargetFontSizePx) diff --git a/Dalamud/Interface/TitleScreenMenu.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs similarity index 50% rename from Dalamud/Interface/TitleScreenMenu.cs rename to Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs index c9e1458d6..3123ffbb8 100644 --- a/Dalamud/Interface/TitleScreenMenu.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs @@ -1,10 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Reflection; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using ImGuiScene; namespace Dalamud.Interface; @@ -12,10 +12,9 @@ namespace Dalamud.Interface; /// /// Class responsible for managing elements in the title screen menu. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public class TitleScreenMenu : IServiceType +internal class TitleScreenMenu : IServiceType, ITitleScreenMenu { /// /// Gets the texture size needed for title screen menu logos. @@ -29,19 +28,10 @@ public class TitleScreenMenu : IServiceType { } - /// - /// Gets the list of entries in the title screen menu. - /// + /// public IReadOnlyList Entries => this.entries; - /// - /// Adds a new entry to the title screen menu. - /// - /// The text to show. - /// The texture to show. - /// The action to execute when the option is selected. - /// A object that can be used to manage the entry. - /// Thrown when the texture provided does not match the required resolution(64x64). + /// public TitleScreenMenuEntry AddEntry(string text, TextureWrap texture, Action onTriggered) { if (texture.Height != TextureSize || texture.Width != TextureSize) @@ -64,15 +54,7 @@ public class TitleScreenMenu : IServiceType } } - /// - /// Adds a new entry to the title screen menu. - /// - /// Priority of the entry. - /// The text to show. - /// The texture to show. - /// The action to execute when the option is selected. - /// A object that can be used to manage the entry. - /// Thrown when the texture provided does not match the required resolution(64x64). + /// public TitleScreenMenuEntry AddEntry(ulong priority, string text, TextureWrap texture, Action onTriggered) { if (texture.Height != TextureSize || texture.Width != TextureSize) @@ -91,10 +73,7 @@ public class TitleScreenMenu : IServiceType } } - /// - /// Remove an entry from the title screen menu. - /// - /// The entry to remove. + /// public void RemoveEntry(TitleScreenMenuEntry entry) { lock (this.entries) @@ -159,93 +138,58 @@ public class TitleScreenMenu : IServiceType return entry; } } +} - /// - /// Class representing an entry in the title screen menu. - /// - public class TitleScreenMenuEntry : IComparable +/// +/// Plugin-scoped version of a TitleScreenMenu service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class TitleScreenMenuPluginScoped : IDisposable, IServiceType, ITitleScreenMenu +{ + [ServiceManager.ServiceDependency] + private readonly TitleScreenMenu titleScreenMenuService = Service.Get(); + + private readonly List pluginEntries = new(); + + /// + public IReadOnlyList? Entries => this.titleScreenMenuService.Entries; + + /// + public void Dispose() { - private readonly Action onTriggered; - - /// - /// Initializes a new instance of the class. - /// - /// The calling assembly. - /// The priority of this entry. - /// The text to show. - /// The texture to show. - /// The action to execute when the option is selected. - internal TitleScreenMenuEntry(Assembly? callingAssembly, ulong priority, string text, TextureWrap texture, Action onTriggered) + foreach (var entry in this.pluginEntries) { - this.CallingAssembly = callingAssembly; - this.Priority = priority; - this.Name = text; - this.Texture = texture; - this.onTriggered = onTriggered; - } - - /// - /// Gets the priority of this entry. - /// - public ulong Priority { get; init; } - - /// - /// Gets or sets the name of this entry. - /// - public string Name { get; set; } - - /// - /// Gets or sets the texture of this entry. - /// - public TextureWrap Texture { get; set; } - - /// - /// Gets or sets a value indicating whether or not this entry is internal. - /// - internal bool IsInternal { get; set; } - - /// - /// Gets the calling assembly of this entry. - /// - internal Assembly? CallingAssembly { get; init; } - - /// - /// Gets the internal ID of this entry. - /// - internal Guid Id { get; init; } = Guid.NewGuid(); - - /// - public int CompareTo(TitleScreenMenuEntry? other) - { - if (other == null) - return 1; - if (this.CallingAssembly != other.CallingAssembly) - { - if (this.CallingAssembly == null && other.CallingAssembly == null) - return 0; - if (this.CallingAssembly == null && other.CallingAssembly != null) - return -1; - if (this.CallingAssembly != null && other.CallingAssembly == null) - return 1; - return string.Compare( - this.CallingAssembly!.FullName!, - other.CallingAssembly!.FullName!, - StringComparison.CurrentCultureIgnoreCase); - } - - if (this.Priority != other.Priority) - return this.Priority.CompareTo(other.Priority); - if (this.Name != other.Name) - return string.Compare(this.Name, other.Name, StringComparison.InvariantCultureIgnoreCase); - return string.Compare(this.Name, other.Name, StringComparison.InvariantCulture); - } - - /// - /// Trigger the action associated with this entry. - /// - internal void Trigger() - { - this.onTriggered(); + this.titleScreenMenuService.RemoveEntry(entry); } } + + /// + public TitleScreenMenuEntry AddEntry(string text, TextureWrap texture, Action onTriggered) + { + var entry = this.titleScreenMenuService.AddEntry(text, texture, onTriggered); + this.pluginEntries.Add(entry); + + return entry; + } + + /// + public TitleScreenMenuEntry AddEntry(ulong priority, string text, TextureWrap texture, Action onTriggered) + { + var entry = this.titleScreenMenuService.AddEntry(priority, text, texture, onTriggered); + this.pluginEntries.Add(entry); + + return entry; + } + + /// + public void RemoveEntry(TitleScreenMenuEntry entry) + { + this.pluginEntries.Remove(entry); + this.titleScreenMenuService.RemoveEntry(entry); + } } diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs new file mode 100644 index 000000000..18acc4f47 --- /dev/null +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs @@ -0,0 +1,94 @@ +using System.Reflection; + +using ImGuiScene; + +namespace Dalamud.Interface; + +/// +/// Class representing an entry in the title screen menu. +/// +public class TitleScreenMenuEntry : IComparable +{ + private readonly Action onTriggered; + + /// + /// Initializes a new instance of the class. + /// + /// The calling assembly. + /// The priority of this entry. + /// The text to show. + /// The texture to show. + /// The action to execute when the option is selected. + internal TitleScreenMenuEntry(Assembly? callingAssembly, ulong priority, string text, TextureWrap texture, Action onTriggered) + { + this.CallingAssembly = callingAssembly; + this.Priority = priority; + this.Name = text; + this.Texture = texture; + this.onTriggered = onTriggered; + } + + /// + /// Gets the priority of this entry. + /// + public ulong Priority { get; init; } + + /// + /// Gets or sets the name of this entry. + /// + public string Name { get; set; } + + /// + /// Gets or sets the texture of this entry. + /// + public TextureWrap Texture { get; set; } + + /// + /// Gets or sets a value indicating whether or not this entry is internal. + /// + internal bool IsInternal { get; set; } + + /// + /// Gets the calling assembly of this entry. + /// + internal Assembly? CallingAssembly { get; init; } + + /// + /// Gets the internal ID of this entry. + /// + internal Guid Id { get; init; } = Guid.NewGuid(); + + /// + public int CompareTo(TitleScreenMenuEntry? other) + { + if (other == null) + return 1; + if (this.CallingAssembly != other.CallingAssembly) + { + if (this.CallingAssembly == null && other.CallingAssembly == null) + return 0; + if (this.CallingAssembly == null && other.CallingAssembly != null) + return -1; + if (this.CallingAssembly != null && other.CallingAssembly == null) + return 1; + return string.Compare( + this.CallingAssembly!.FullName!, + other.CallingAssembly!.FullName!, + StringComparison.CurrentCultureIgnoreCase); + } + + if (this.Priority != other.Priority) + return this.Priority.CompareTo(other.Priority); + if (this.Name != other.Name) + return string.Compare(this.Name, other.Name, StringComparison.InvariantCultureIgnoreCase); + return 0; + } + + /// + /// Trigger the action associated with this entry. + /// + internal void Trigger() + { + this.onTriggered(); + } +} diff --git a/Dalamud/Plugin/Services/ITitleScreenMenu.cs b/Dalamud/Plugin/Services/ITitleScreenMenu.cs new file mode 100644 index 000000000..2094dc435 --- /dev/null +++ b/Dalamud/Plugin/Services/ITitleScreenMenu.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; + +using Dalamud.Interface; +using ImGuiScene; + +namespace Dalamud.Plugin.Services; + +/// +/// Interface for class responsible for managing elements in the title screen menu. +/// +public interface ITitleScreenMenu +{ + /// + /// Gets the list of entries in the title screen menu. + /// + public IReadOnlyList Entries { get; } + + /// + /// Adds a new entry to the title screen menu. + /// + /// The text to show. + /// The texture to show. + /// The action to execute when the option is selected. + /// A object that can be used to manage the entry. + /// Thrown when the texture provided does not match the required resolution(64x64). + public TitleScreenMenuEntry AddEntry(string text, TextureWrap texture, Action onTriggered); + + /// + /// Adds a new entry to the title screen menu. + /// + /// Priority of the entry. + /// The text to show. + /// The texture to show. + /// The action to execute when the option is selected. + /// A object that can be used to manage the entry. + /// Thrown when the texture provided does not match the required resolution(64x64). + public TitleScreenMenuEntry AddEntry(ulong priority, string text, TextureWrap texture, Action onTriggered); + + /// + /// Remove an entry from the title screen menu. + /// + /// The entry to remove. + public void RemoveEntry(TitleScreenMenuEntry entry); +} From 181ec6b95623b6cf15c3b7063785c7976065bc4a Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:07:46 -0700 Subject: [PATCH 042/120] Add GameNetworkPluginScoped (#1380) --- Dalamud/Game/Network/GameNetwork.cs | 52 +++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/Dalamud/Game/Network/GameNetwork.cs b/Dalamud/Game/Network/GameNetwork.cs index 2b6630c8b..f56fd3996 100644 --- a/Dalamud/Game/Network/GameNetwork.cs +++ b/Dalamud/Game/Network/GameNetwork.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using Dalamud.Configuration.Internal; @@ -14,13 +13,9 @@ namespace Dalamud.Game.Network; /// /// This class handles interacting with game network events. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork +internal sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork { private readonly GameNetworkAddressResolver address; private readonly Hook processZonePacketDownHook; @@ -57,14 +52,10 @@ public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate byte ProcessZonePacketUpDelegate(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4); - /// - /// Event that is called when a network message is sent/received. - /// - public event IGameNetwork.OnNetworkMessageDelegate NetworkMessage; + /// + public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage; - /// - /// Dispose of managed and unmanaged resources. - /// + /// void IDisposable.Dispose() { this.processZonePacketDownHook.Dispose(); @@ -148,3 +139,38 @@ public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4); } } + +/// +/// Plugin-scoped version of a AddonLifecycle service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class GameNetworkPluginScoped : IDisposable, IServiceType, IGameNetwork +{ + [ServiceManager.ServiceDependency] + private readonly GameNetwork gameNetworkService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal GameNetworkPluginScoped() + { + this.gameNetworkService.NetworkMessage += this.NetworkMessageForward; + } + + /// + public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage; + + /// + public void Dispose() + { + this.gameNetworkService.NetworkMessage -= this.NetworkMessageForward; + } + + private void NetworkMessageForward(nint dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) + => this.NetworkMessage?.Invoke(dataPtr, opCode, sourceActorId, targetActorId, direction); +} From abf7c243e428166bcfd9b9dc71b28a3d24412c32 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:09:01 -0700 Subject: [PATCH 043/120] Add GameGuiPluginScoped (#1381) --- Dalamud/Game/Gui/GameGui.cs | 143 +++++++++++++++++++++++++++++------- 1 file changed, 117 insertions(+), 26 deletions(-) diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 3954954a3..078c624e8 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -1,13 +1,12 @@ -using System; using System.Numerics; using System.Runtime.InteropServices; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Hooking; -using Dalamud.Interface; using Dalamud.Interface.Utility; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; @@ -16,7 +15,6 @@ using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; using FFXIVClientStructs.FFXIV.Component.GUI; using ImGuiNET; -using Serilog; using SharpDX; using Vector2 = System.Numerics.Vector2; @@ -27,14 +25,12 @@ namespace Dalamud.Game.Gui; /// /// A class handling many aspects of the in-game UI. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui +internal sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui { + private static readonly ModuleLog Log = new("GameGui"); + private readonly GameGuiAddressResolver address; private readonly GetMatrixSingletonDelegate getMatrixSingleton; @@ -48,8 +44,8 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui private readonly Hook toggleUiHideHook; private readonly Hook utf8StringFromSequenceHook; - private GetUIMapObjectDelegate getUIMapObject; - private OpenMapWithFlagDelegate openMapWithFlag; + private GetUIMapObjectDelegate? getUIMapObject; + private OpenMapWithFlagDelegate? openMapWithFlag; [ServiceManager.ServiceConstructor] private GameGui(SigScanner sigScanner) @@ -116,16 +112,16 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui private delegate char HandleImmDelegate(IntPtr framework, char a2, byte a3); [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr ToggleUiHideDelegate(IntPtr thisPtr, byte unknownByte); + private delegate IntPtr ToggleUiHideDelegate(IntPtr thisPtr, bool uiVisible); /// - public event EventHandler UiHideToggled; + public event EventHandler? UiHideToggled; /// - public event EventHandler HoveredItemChanged; + public event EventHandler? HoveredItemChanged; /// - public event EventHandler HoveredActionChanged; + public event EventHandler? HoveredActionChanged; /// public bool GameUiHidden { get; private set; } @@ -147,7 +143,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui return false; } - this.getUIMapObject = this.address.GetVirtualFunction(uiModule, 0, 8); + this.getUIMapObject ??= this.address.GetVirtualFunction(uiModule, 0, 8); var uiMapObjectPtr = this.getUIMapObject(uiModule); @@ -157,7 +153,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui return false; } - this.openMapWithFlag = this.address.GetVirtualFunction(uiMapObjectPtr, 0, 63); + this.openMapWithFlag ??= this.address.GetVirtualFunction(uiMapObjectPtr, 0, 63); var mapLinkString = mapLink.DataString; @@ -217,14 +213,13 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui // Read current ViewProjectionMatrix plus game window size var viewProjectionMatrix = default(Matrix); - float width, height; var rawMatrix = (float*)(matrixSingleton + 0x1b4).ToPointer(); for (var i = 0; i < 16; i++, rawMatrix++) viewProjectionMatrix[i] = *rawMatrix; - width = *rawMatrix; - height = *(rawMatrix + 1); + var width = *rawMatrix; + var height = *(rawMatrix + 1); viewProjectionMatrix.Invert(); @@ -414,7 +409,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui this.HoveredItemChanged?.InvokeSafely(this, itemId); - Log.Verbose("HoverItemId:{0} this:{1}", itemId, hoverState.ToInt64().ToString("X")); + Log.Verbose($"HoverItemId:{itemId} this:{hoverState.ToInt64()}"); } return retVal; @@ -456,7 +451,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui this.HoveredAction.ActionID = (uint)Marshal.ReadInt32(hoverState, 0x3C); this.HoveredActionChanged?.InvokeSafely(this, this.HoveredAction); - Log.Verbose("HoverActionId: {0}/{1} this:{2}", actionKind, actionId, hoverState.ToInt64().ToString("X")); + Log.Verbose($"HoverActionId: {actionKind}/{actionId} this:{hoverState.ToInt64():X}"); } private IntPtr HandleActionOutDetour(IntPtr agentActionDetail, IntPtr a2, IntPtr a3, int a4) @@ -489,16 +484,15 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui return retVal; } - private IntPtr ToggleUiHideDetour(IntPtr thisPtr, byte unknownByte) + private IntPtr ToggleUiHideDetour(IntPtr thisPtr, bool uiVisible) { - // TODO(goat): We should read this from memory directly, instead of relying on catching every toggle. - this.GameUiHidden = !this.GameUiHidden; + this.GameUiHidden = !RaptureAtkModule.Instance()->IsUiVisible; this.UiHideToggled?.InvokeSafely(this, this.GameUiHidden); Log.Debug("UiHide toggled: {0}", this.GameUiHidden); - return this.toggleUiHideHook.Original(thisPtr, unknownByte); + return this.toggleUiHideHook.Original(thisPtr, uiVisible); } private char HandleImmDetour(IntPtr framework, char a2, byte a3) @@ -514,8 +508,105 @@ public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui if (sourcePtr != null) this.utf8StringFromSequenceHook.Original(thisPtr, sourcePtr, sourceLen); else - thisPtr->Ctor(); // this is in clientstructs but you could do it manually too + thisPtr->Ctor(); // this is in ClientStructs but you could do it manually too return thisPtr; // this function shouldn't need to return but the original asm moves this into rax before returning so be safe? } } + +/// +/// Plugin-scoped version of a AddonLifecycle service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class GameGuiPluginScoped : IDisposable, IServiceType, IGameGui +{ + [ServiceManager.ServiceDependency] + private readonly GameGui gameGuiService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal GameGuiPluginScoped() + { + this.gameGuiService.UiHideToggled += this.UiHideToggledForward; + this.gameGuiService.HoveredItemChanged += this.HoveredItemForward; + this.gameGuiService.HoveredActionChanged += this.HoveredActionForward; + } + + /// + public event EventHandler? UiHideToggled; + + /// + public event EventHandler? HoveredItemChanged; + + /// + public event EventHandler? HoveredActionChanged; + + /// + public bool GameUiHidden => this.gameGuiService.GameUiHidden; + + /// + public ulong HoveredItem + { + get => this.gameGuiService.HoveredItem; + set => this.gameGuiService.HoveredItem = value; + } + + /// + public HoveredAction HoveredAction => this.gameGuiService.HoveredAction; + + /// + public void Dispose() + { + this.gameGuiService.UiHideToggled -= this.UiHideToggledForward; + this.gameGuiService.HoveredItemChanged -= this.HoveredItemForward; + this.gameGuiService.HoveredActionChanged -= this.HoveredActionForward; + } + + /// + public bool OpenMapWithMapLink(MapLinkPayload mapLink) + => this.gameGuiService.OpenMapWithMapLink(mapLink); + + /// + public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos) + => this.gameGuiService.WorldToScreen(worldPos, out screenPos); + + /// + public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos, out bool inView) + => this.gameGuiService.WorldToScreen(worldPos, out screenPos, out inView); + + /// + public bool ScreenToWorld(Vector2 screenPos, out Vector3 worldPos, float rayDistance = 100000) + => this.gameGuiService.ScreenToWorld(screenPos, out worldPos, rayDistance); + + /// + public IntPtr GetUIModule() + => this.gameGuiService.GetUIModule(); + + /// + public IntPtr GetAddonByName(string name, int index = 1) + => this.gameGuiService.GetAddonByName(name, index); + + /// + public IntPtr FindAgentInterface(string addonName) + => this.gameGuiService.FindAgentInterface(addonName); + + /// + public unsafe IntPtr FindAgentInterface(void* addon) + => this.gameGuiService.FindAgentInterface(addon); + + /// + public IntPtr FindAgentInterface(IntPtr addonPtr) + => this.gameGuiService.FindAgentInterface(addonPtr); + + private void UiHideToggledForward(object sender, bool toggled) => this.UiHideToggled?.Invoke(sender, toggled); + + private void HoveredItemForward(object sender, ulong itemId) => this.HoveredItemChanged?.Invoke(sender, itemId); + + private void HoveredActionForward(object sender, HoveredAction hoverAction) => this.HoveredActionChanged?.Invoke(sender, hoverAction); +} From d96175ed16920f36e5851df736016657f11a9cda Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:10:36 -0700 Subject: [PATCH 044/120] Add DutyStatePluginScoped (#1382) --- Dalamud/Game/DutyState/DutyState.cs | 95 ++++++++++++++----- .../DutyState/DutyStateAddressResolver.cs | 2 - Dalamud/Plugin/Services/IDutyState.cs | 4 +- 3 files changed, 74 insertions(+), 27 deletions(-) diff --git a/Dalamud/Game/DutyState/DutyState.cs b/Dalamud/Game/DutyState/DutyState.cs index 49fc874e3..2f117a492 100644 --- a/Dalamud/Game/DutyState/DutyState.cs +++ b/Dalamud/Game/DutyState/DutyState.cs @@ -1,25 +1,19 @@ -using System; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using Dalamud.Game.ClientState.Conditions; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; -using Dalamud.Utility; namespace Dalamud.Game.DutyState; /// /// This class represents the state of the currently occupied duty. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.EarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -public unsafe class DutyState : IDisposable, IServiceType, IDutyState +internal unsafe class DutyState : IDisposable, IServiceType, IDutyState { private readonly DutyStateAddressResolver address; private readonly Hook contentDirectorNetworkMessageHook; @@ -49,16 +43,16 @@ public unsafe class DutyState : IDisposable, IServiceType, IDutyState private delegate byte SetupContentDirectNetworkMessageDelegate(IntPtr a1, IntPtr a2, ushort* a3); /// - public event EventHandler DutyStarted; + public event EventHandler? DutyStarted; /// - public event EventHandler DutyWiped; + public event EventHandler? DutyWiped; /// - public event EventHandler DutyRecommenced; + public event EventHandler? DutyRecommenced; /// - public event EventHandler DutyCompleted; + public event EventHandler? DutyCompleted; /// public bool IsDutyStarted { get; private set; } @@ -66,7 +60,7 @@ public unsafe class DutyState : IDisposable, IServiceType, IDutyState private bool CompletedThisTerritory { get; set; } /// - void IDisposable.Dispose() + public void Dispose() { this.contentDirectorNetworkMessageHook.Dispose(); this.framework.Update -= this.FrameworkOnUpdateEvent; @@ -92,33 +86,33 @@ public unsafe class DutyState : IDisposable, IServiceType, IDutyState // Duty Commenced case 0x4000_0001: this.IsDutyStarted = true; - this.DutyStarted.InvokeSafely(this, this.clientState.TerritoryType); + this.DutyStarted?.Invoke(this, this.clientState.TerritoryType); break; // Party Wipe case 0x4000_0005: this.IsDutyStarted = false; - this.DutyWiped.InvokeSafely(this, this.clientState.TerritoryType); + this.DutyWiped?.Invoke(this, this.clientState.TerritoryType); break; // Duty Recommence case 0x4000_0006: this.IsDutyStarted = true; - this.DutyRecommenced.InvokeSafely(this, this.clientState.TerritoryType); + this.DutyRecommenced?.Invoke(this, this.clientState.TerritoryType); break; // Duty Completed Flytext Shown case 0x4000_0002 when !this.CompletedThisTerritory: this.IsDutyStarted = false; this.CompletedThisTerritory = true; - this.DutyCompleted.InvokeSafely(this, this.clientState.TerritoryType); + this.DutyCompleted?.Invoke(this, this.clientState.TerritoryType); break; // Duty Completed case 0x4000_0003 when !this.CompletedThisTerritory: this.IsDutyStarted = false; this.CompletedThisTerritory = true; - this.DutyCompleted.InvokeSafely(this, this.clientState.TerritoryType); + this.DutyCompleted?.Invoke(this, this.clientState.TerritoryType); break; } } @@ -161,11 +155,68 @@ public unsafe class DutyState : IDisposable, IServiceType, IDutyState } private bool IsBoundByDuty() + => this.condition.Any(ConditionFlag.BoundByDuty, + ConditionFlag.BoundByDuty56, + ConditionFlag.BoundByDuty95); + + private bool IsInCombat() + => this.condition.Any(ConditionFlag.InCombat); +} + +/// +/// Plugin scoped version of DutyState. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class DutyStatePluginScoped : IDisposable, IServiceType, IDutyState +{ + [ServiceManager.ServiceDependency] + private readonly DutyState dutyStateService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal DutyStatePluginScoped() { - return this.condition[ConditionFlag.BoundByDuty] || - this.condition[ConditionFlag.BoundByDuty56] || - this.condition[ConditionFlag.BoundByDuty95]; + this.dutyStateService.DutyStarted += this.DutyStartedForward; + this.dutyStateService.DutyWiped += this.DutyWipedForward; + this.dutyStateService.DutyRecommenced += this.DutyRecommencedForward; + this.dutyStateService.DutyCompleted += this.DutyCompletedForward; } - private bool IsInCombat() => this.condition[ConditionFlag.InCombat]; + /// + public event EventHandler? DutyStarted; + + /// + public event EventHandler? DutyWiped; + + /// + public event EventHandler? DutyRecommenced; + + /// + public event EventHandler? DutyCompleted; + + /// + public bool IsDutyStarted => this.dutyStateService.IsDutyStarted; + + /// + public void Dispose() + { + this.dutyStateService.DutyStarted -= this.DutyStartedForward; + this.dutyStateService.DutyWiped -= this.DutyWipedForward; + this.dutyStateService.DutyRecommenced -= this.DutyRecommencedForward; + this.dutyStateService.DutyCompleted -= this.DutyCompletedForward; + } + + private void DutyStartedForward(object sender, ushort territoryId) => this.DutyStarted?.Invoke(sender, territoryId); + + private void DutyWipedForward(object sender, ushort territoryId) => this.DutyWiped?.Invoke(sender, territoryId); + + private void DutyRecommencedForward(object sender, ushort territoryId) => this.DutyRecommenced?.Invoke(sender, territoryId); + + private void DutyCompletedForward(object sender, ushort territoryId) => this.DutyCompleted?.Invoke(sender, territoryId); } diff --git a/Dalamud/Game/DutyState/DutyStateAddressResolver.cs b/Dalamud/Game/DutyState/DutyStateAddressResolver.cs index 801e5ef55..436883dc2 100644 --- a/Dalamud/Game/DutyState/DutyStateAddressResolver.cs +++ b/Dalamud/Game/DutyState/DutyStateAddressResolver.cs @@ -1,5 +1,3 @@ -using System; - namespace Dalamud.Game.DutyState; /// diff --git a/Dalamud/Plugin/Services/IDutyState.cs b/Dalamud/Plugin/Services/IDutyState.cs index a2331364c..3d49f68cb 100644 --- a/Dalamud/Plugin/Services/IDutyState.cs +++ b/Dalamud/Plugin/Services/IDutyState.cs @@ -1,6 +1,4 @@ -using System; - -namespace Dalamud.Plugin.Services; +namespace Dalamud.Plugin.Services; /// /// This class represents the state of the currently occupied duty. From e3d688141c21daaa3d8b8f04bb7140edf83b956c Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 11 Sep 2023 22:20:05 -0700 Subject: [PATCH 045/120] Add ConditionPluginScoped (#1385) --- .../Game/ClientState/Conditions/Condition.cs | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/Dalamud/Game/ClientState/Conditions/Condition.cs b/Dalamud/Game/ClientState/Conditions/Condition.cs index b72c91c74..585b762bf 100644 --- a/Dalamud/Game/ClientState/Conditions/Condition.cs +++ b/Dalamud/Game/ClientState/Conditions/Condition.cs @@ -10,13 +10,9 @@ namespace Dalamud.Game.ClientState.Conditions; /// /// Provides access to conditions (generally player state). You can check whether a player is in combat, mounted, etc. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -public sealed partial class Condition : IServiceType, ICondition +internal sealed partial class Condition : IServiceType, ICondition { /// /// Gets the current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has. @@ -122,7 +118,7 @@ public sealed partial class Condition : IServiceType, ICondition /// /// Provides access to conditions (generally player state). You can check whether a player is in combat, mounted, etc. /// -public sealed partial class Condition : IDisposable +internal sealed partial class Condition : IDisposable { private bool isDisposed; @@ -156,3 +152,52 @@ public sealed partial class Condition : IDisposable this.isDisposed = true; } } + +/// +/// Plugin-scoped version of a Condition service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class ConditionPluginScoped : IDisposable, IServiceType, ICondition +{ + [ServiceManager.ServiceDependency] + private readonly Condition conditionService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal ConditionPluginScoped() + { + this.conditionService.ConditionChange += this.ConditionChangedForward; + } + + /// + public event ICondition.ConditionChangeDelegate? ConditionChange; + + /// + public int MaxEntries => this.conditionService.MaxEntries; + + /// + public IntPtr Address => this.conditionService.Address; + + /// + public bool this[int flag] => this.conditionService[flag]; + + /// + public void Dispose() + { + this.conditionService.ConditionChange -= this.ConditionChangedForward; + } + + /// + public bool Any() => this.conditionService.Any(); + + /// + public bool Any(params ConditionFlag[] flags) => this.conditionService.Any(flags); + + private void ConditionChangedForward(ConditionFlag flag, bool value) => this.ConditionChange?.Invoke(flag, value); +} From 3e613cffd0b032f68d8bcca4564731bc29eea691 Mon Sep 17 00:00:00 2001 From: bleatbot <106497096+bleatbot@users.noreply.github.com> Date: Tue, 12 Sep 2023 07:20:20 +0200 Subject: [PATCH 046/120] Update ClientStructs (#1371) (#1387) Co-authored-by: github-actions[bot] --- lib/FFXIVClientStructs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index ada62e7ae..7279a8f3c 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit ada62e7ae60de220d1f950b03ddb8d66e9e10daf +Subproject commit 7279a8f3ca6b79490184b05532af509781a89415 From fd518f8e3f6123835733e6714f5840eae108bacf Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Sun, 20 Aug 2023 16:14:42 -0700 Subject: [PATCH 047/120] fix: Don't check for Wine Registry anymore - Renames `IsLinux` to `IsWine` to better reflect that this will return true for macOS as well. - Fixes a bug caused by misbehaving apps wanting to be helpful to Linux users - Also makes Wine checking far more resilient in cases where XL_WINEONLINUX isn't set. --- Dalamud/Utility/Util.cs | 42 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 5f2e4d5bf..63fc9faee 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using Dalamud.Configuration.Internal; @@ -22,7 +23,6 @@ using Dalamud.Logging.Internal; using Dalamud.Networking.Http; using ImGuiNET; using Lumina.Excel.GeneratedSheets; -using Microsoft.Win32; using Serilog; namespace Dalamud.Utility; @@ -491,32 +491,30 @@ public static class Util } /// - /// Heuristically determine if Dalamud is running on Linux/WINE. + /// Determine if Dalamud is currently running within a Wine context (e.g. either on macOS or Linux). This method + /// will not return information about the host operating system. /// - /// Whether or not Dalamud is running on Linux/WINE. - public static bool IsLinux() + /// Returns true if Wine is detected, false otherwise. + public static bool IsWine() { - bool Check1() - { - return EnvironmentConfiguration.XlWineOnLinux; - } + if (EnvironmentConfiguration.XlWineOnLinux) return true; - bool Check2() - { - var hModule = NativeFunctions.GetModuleHandleW("ntdll.dll"); - var proc1 = NativeFunctions.GetProcAddress(hModule, "wine_get_version"); - var proc2 = NativeFunctions.GetProcAddress(hModule, "wine_get_build_id"); + var ntdll = NativeFunctions.GetModuleHandleW("ntdll.dll"); - return proc1 != IntPtr.Zero || proc2 != IntPtr.Zero; - } + // Test to see if any Wine specific exports exist. If they do, then we are running on Wine. + // The exports "wine_get_version", "wine_get_build_id", and "wine_get_host_version" will tend to be hidden + // by most Linux users (else FFXIV will want a macOS license), so we will additionally check some lesser-known + // exports as well. + return AnyProcExists( + ntdll, + "wine_get_version", + "wine_get_build_id", + "wine_get_host_version", + "wine_server_call", + "wine_unix_to_nt_file_name"); - bool Check3() - { - return Registry.CurrentUser.OpenSubKey(@"Software\Wine") != null || - Registry.LocalMachine.OpenSubKey(@"Software\Wine") != null; - } - - return Check1() || Check2() || Check3(); + bool AnyProcExists(nint handle, params string[] procs) => + procs.Any(p => NativeFunctions.GetProcAddress(handle, p) != nint.Zero); } /// From 2acba2b81f93cdd6dd766c9140389c9ec12ded08 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Tue, 12 Sep 2023 17:06:22 -0700 Subject: [PATCH 048/120] Update Dalamud.Boot to use extra import checks - Ports extra import checks to Dalamud Boot - Renames is_running_on_linux to is_running_on_wine - Update relevant logging string for VEH --- Dalamud.Boot/dllmain.cpp | 4 ++-- Dalamud.Boot/utils.cpp | 6 +++++- Dalamud.Boot/utils.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp index 9a741a47f..94f1c7d0f 100644 --- a/Dalamud.Boot/dllmain.cpp +++ b/Dalamud.Boot/dllmain.cpp @@ -133,8 +133,8 @@ DWORD WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) { // ============================== VEH ======================================== // logging::I("Initializing VEH..."); - if (utils::is_running_on_linux()) { - logging::I("=> VEH was disabled, running on linux"); + if (utils::is_running_on_wine()) { + logging::I("=> VEH was disabled, running on wine"); } else if (g_startInfo.BootVehEnabled) { if (veh::add_handler(g_startInfo.BootVehFull, g_startInfo.WorkingDirectory)) logging::I("=> Done!"); diff --git a/Dalamud.Boot/utils.cpp b/Dalamud.Boot/utils.cpp index 79205eb8d..b45795045 100644 --- a/Dalamud.Boot/utils.cpp +++ b/Dalamud.Boot/utils.cpp @@ -578,7 +578,7 @@ std::vector utils::get_env_list(const wchar_t* pcszName) { return res; } -bool utils::is_running_on_linux() { +bool utils::is_running_on_wine() { if (get_env(L"XL_WINEONLINUX")) return true; HMODULE hntdll = GetModuleHandleW(L"ntdll.dll"); @@ -588,6 +588,10 @@ bool utils::is_running_on_linux() { return true; if (GetProcAddress(hntdll, "wine_get_host_version")) return true; + if (GetProcAddress(hntdll, "wine_server_call")) + return true; + if (GetProcAddress(hntdll, "wine_unix_to_nt_file_name")) + return true; return false; } diff --git a/Dalamud.Boot/utils.h b/Dalamud.Boot/utils.h index 5d5c90dde..5e3caa4d6 100644 --- a/Dalamud.Boot/utils.h +++ b/Dalamud.Boot/utils.h @@ -264,7 +264,7 @@ namespace utils { return get_env_list(unicode::convert(pcszName).c_str()); } - bool is_running_on_linux(); + bool is_running_on_wine(); std::filesystem::path get_module_path(HMODULE hModule); From 0fca2c80c30457f9634e1d12be437ae51dc02b49 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Tue, 12 Sep 2023 18:14:54 -0700 Subject: [PATCH 049/120] Fix a build error, oops --- Dalamud/EntryPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 1975505a8..7ad794e42 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -166,7 +166,7 @@ public sealed class EntryPoint // This is due to GitHub not supporting TLS 1.0, so we enable all TLS versions globally ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls; - if (!Util.IsLinux()) + if (!Util.IsWine()) InitSymbolHandler(info); var dalamud = new Dalamud(info, configuration, mainThreadContinueEvent); From a7aacb15e4603a367e2f980578271a9a639d8852 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Tue, 12 Sep 2023 18:22:20 -0700 Subject: [PATCH 050/120] Add XL_PLATFORM env var, Util.GetHostPlatform() - New env var XL_PLATFORM allows launcher to inform Dalamud of the current platform (one of Windows, macOS, or Linux). - New method Util.GetHostPlatform() provides a best guess for the current platform. This method will respect XL_PLATFORM if set, but will otherwise resort to heuristic checks. --- Dalamud/Utility/Util.cs | 68 +++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 63fc9faee..5be4e4fc4 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; -using System.Net.Http; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; @@ -16,11 +14,10 @@ using Dalamud.Data; using Dalamud.Game; using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Utility; using Dalamud.Logging.Internal; -using Dalamud.Networking.Http; +using Dalamud.Memory; using ImGuiNET; using Lumina.Excel.GeneratedSheets; using Serilog; @@ -38,7 +35,7 @@ public static class Util private static ulong moduleStartAddr; private static ulong moduleEndAddr; - + /// /// Gets the assembly version of Dalamud. /// @@ -498,6 +495,7 @@ public static class Util public static bool IsWine() { if (EnvironmentConfiguration.XlWineOnLinux) return true; + if (Environment.GetEnvironmentVariable("XL_PLATFORM") is not null and not "Windows") return true; var ntdll = NativeFunctions.GetModuleHandleW("ntdll.dll"); @@ -506,17 +504,46 @@ public static class Util // by most Linux users (else FFXIV will want a macOS license), so we will additionally check some lesser-known // exports as well. return AnyProcExists( - ntdll, - "wine_get_version", - "wine_get_build_id", + ntdll, + "wine_get_version", + "wine_get_build_id", "wine_get_host_version", - "wine_server_call", + "wine_server_call", "wine_unix_to_nt_file_name"); bool AnyProcExists(nint handle, params string[] procs) => procs.Any(p => NativeFunctions.GetProcAddress(handle, p) != nint.Zero); } + /// + /// Gets the best guess for the current host's platform based on the XL_PLATFORM environment variable or + /// heuristics. + /// + /// + /// This method is not perfectly reliable if XL_PLATFORM is unset. For example, macOS users running with + /// exports hidden will be marked as Linux users. Better heuristic checks for macOS are needed in order to fix this. + /// + /// Returns the that Dalamud is currently running on. + public static OSPlatform GetHostPlatform() + { + switch (Environment.GetEnvironmentVariable("XL_PLATFORM")) + { + case "Windows": return OSPlatform.Windows; + case "MacOS": return OSPlatform.OSX; + case "Linux": return OSPlatform.Linux; + } + + if (IsWine()) + { + GetWineHostVersion(out var platform, out _); + if (platform == "Darwin") return OSPlatform.OSX; // only happens on macOS without export hides (mac license) + + return OSPlatform.Linux; + } + + return OSPlatform.Windows; + } + /// /// Heuristically determine if the Windows version is higher than Windows 11's first build. /// @@ -683,7 +710,7 @@ public static class Util ImGui.SetClipboardText(actor.Address.ToInt64().ToString("X")); } } - + private static unsafe void ShowValue(ulong addr, IEnumerable path, Type type, object value) { if (type.IsPointer) @@ -738,4 +765,25 @@ public static class Util } } } + + private static unsafe bool GetWineHostVersion(out string? platform, out string? version) + { + platform = null; + version = null; + + var ntdll = NativeFunctions.GetModuleHandleW("ntdll.dll"); + var methodPtr = NativeFunctions.GetProcAddress(ntdll, "wine_get_host_version"); + + if (methodPtr == nint.Zero) return false; + + var methodDelegate = (delegate* unmanaged[Fastcall])methodPtr; + methodDelegate(out var platformPtr, out var versionPtr); + + if (platformPtr == null) return false; + + platform = MemoryHelper.ReadStringNullTerminated((nint)platformPtr); + if (versionPtr != null) version = MemoryHelper.ReadStringNullTerminated((nint)versionPtr); + + return true; + } } From 088cf8c3922022d5fb576f05b876d7263032226f Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Wed, 13 Sep 2023 00:23:17 -0700 Subject: [PATCH 051/120] Remove fancy Darwin checking code --- Dalamud/Utility/Util.cs | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 5be4e4fc4..78edda3dd 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -520,8 +520,8 @@ public static class Util /// heuristics. /// /// - /// This method is not perfectly reliable if XL_PLATFORM is unset. For example, macOS users running with - /// exports hidden will be marked as Linux users. Better heuristic checks for macOS are needed in order to fix this. + /// macOS users running without XL_PLATFORM being set will be reported as Linux users. Due to the way our + /// Wines work, there isn't a great (consistent) way to split the two apart if we're not told. /// /// Returns the that Dalamud is currently running on. public static OSPlatform GetHostPlatform() @@ -532,16 +532,13 @@ public static class Util case "MacOS": return OSPlatform.OSX; case "Linux": return OSPlatform.Linux; } - - if (IsWine()) - { - GetWineHostVersion(out var platform, out _); - if (platform == "Darwin") return OSPlatform.OSX; // only happens on macOS without export hides (mac license) - return OSPlatform.Linux; - } + // n.b. we had some fancy code here to check if the Wine host version returned "Darwin" but apparently + // *all* our Wines report Darwin if exports aren't hidden. As such, it is effectively impossible (without some + // (very cursed and inaccurate heuristics) to determine if we're on macOS or Linux unless we're explicitly told + // by our launcher. See commit a7aacb15e4603a367e2f980578271a9a639d8852 for the old check. - return OSPlatform.Windows; + return IsWine() ? OSPlatform.Linux : OSPlatform.Windows; } /// @@ -765,25 +762,4 @@ public static class Util } } } - - private static unsafe bool GetWineHostVersion(out string? platform, out string? version) - { - platform = null; - version = null; - - var ntdll = NativeFunctions.GetModuleHandleW("ntdll.dll"); - var methodPtr = NativeFunctions.GetProcAddress(ntdll, "wine_get_host_version"); - - if (methodPtr == nint.Zero) return false; - - var methodDelegate = (delegate* unmanaged[Fastcall])methodPtr; - methodDelegate(out var platformPtr, out var versionPtr); - - if (platformPtr == null) return false; - - platform = MemoryHelper.ReadStringNullTerminated((nint)platformPtr); - if (versionPtr != null) version = MemoryHelper.ReadStringNullTerminated((nint)versionPtr); - - return true; - } } From 6eba1415f546e38d5fab31d8f71a71dc379bf254 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 24 Jun 2023 22:18:41 -0700 Subject: [PATCH 052/120] Add IChatGui --- Dalamud/Game/Gui/ChatGui.cs | 112 ++++++-------------------- Dalamud/Plugin/Services/IChatGui.cs | 119 ++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 89 deletions(-) create mode 100644 Dalamud/Plugin/Services/IChatGui.cs diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs index 93185caf9..d8154b41d 100644 --- a/Dalamud/Game/Gui/ChatGui.cs +++ b/Dalamud/Game/Gui/ChatGui.cs @@ -11,6 +11,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Plugin.Services; using Dalamud.Utility; using Serilog; @@ -22,7 +23,10 @@ namespace Dalamud.Game.Gui; [PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public sealed class ChatGui : IDisposable, IServiceType +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +public sealed class ChatGui : IDisposable, IServiceType, IChatGui { private readonly ChatGuiAddressResolver address; @@ -51,45 +55,7 @@ public sealed class ChatGui : IDisposable, IServiceType this.populateItemLinkHook = Hook.FromAddress(this.address.PopulateItemLinkObject, this.HandlePopulateItemLinkDetour); this.interactableLinkClickedHook = Hook.FromAddress(this.address.InteractableLinkClicked, this.InteractableLinkClickedDetour); } - - /// - /// A delegate type used with the event. - /// - /// The type of chat. - /// The sender ID. - /// The sender name. - /// The message sent. - /// A value indicating whether the message was handled or should be propagated. - public delegate void OnMessageDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled); - - /// - /// A delegate type used with the event. - /// - /// The type of chat. - /// The sender ID. - /// The sender name. - /// The message sent. - /// A value indicating whether the message was handled or should be propagated. - public delegate void OnCheckMessageHandledDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled); - - /// - /// A delegate type used with the event. - /// - /// The type of chat. - /// The sender ID. - /// The sender name. - /// The message sent. - public delegate void OnMessageHandledDelegate(XivChatType type, uint senderId, SeString sender, SeString message); - - /// - /// A delegate type used with the event. - /// - /// The type of chat. - /// The sender ID. - /// The sender name. - /// The message sent. - public delegate void OnMessageUnhandledDelegate(XivChatType type, uint senderId, SeString sender, SeString message); - + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate IntPtr PrintMessageDelegate(IntPtr manager, XivChatType chatType, IntPtr senderName, IntPtr message, uint senderId, IntPtr parameter); @@ -99,34 +65,22 @@ public sealed class ChatGui : IDisposable, IServiceType [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate void InteractableLinkClickedDelegate(IntPtr managerPtr, IntPtr messagePtr); - /// - /// Event that will be fired when a chat message is sent to chat by the game. - /// - public event OnMessageDelegate ChatMessage; + /// + public event IChatGui.OnMessageDelegate ChatMessage; - /// - /// Event that allows you to stop messages from appearing in chat by setting the isHandled parameter to true. - /// - public event OnCheckMessageHandledDelegate CheckMessageHandled; + /// + public event IChatGui.OnCheckMessageHandledDelegate CheckMessageHandled; - /// - /// Event that will be fired when a chat message is handled by Dalamud or a Plugin. - /// - public event OnMessageHandledDelegate ChatMessageHandled; + /// + public event IChatGui.OnMessageHandledDelegate ChatMessageHandled; - /// - /// Event that will be fired when a chat message is not handled by Dalamud or a Plugin. - /// - public event OnMessageUnhandledDelegate ChatMessageUnhandled; + /// + public event IChatGui.OnMessageUnhandledDelegate ChatMessageUnhandled; - /// - /// Gets the ID of the last linked item. - /// + /// public int LastLinkedItemId { get; private set; } - /// - /// Gets the flags of the last linked item. - /// + /// public byte LastLinkedItemFlags { get; private set; } /// @@ -139,21 +93,13 @@ public sealed class ChatGui : IDisposable, IServiceType this.interactableLinkClickedHook.Dispose(); } - /// - /// Queue a chat message. While method is named as PrintChat, it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. - /// - /// A message to send. + /// public void PrintChat(XivChatEntry chat) { this.chatQueue.Enqueue(chat); } - /// - /// Queue a chat message. While method is named as PrintChat (it calls it internally), it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. - /// - /// A message to send. + /// public void Print(string message) { // Log.Verbose("[CHATGUI PRINT REGULAR]{0}", message); @@ -164,11 +110,7 @@ public sealed class ChatGui : IDisposable, IServiceType }); } - /// - /// Queue a chat message. While method is named as PrintChat (it calls it internally), it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. - /// - /// A message to send. + /// public void Print(SeString message) { // Log.Verbose("[CHATGUI PRINT SESTRING]{0}", message.TextValue); @@ -179,11 +121,7 @@ public sealed class ChatGui : IDisposable, IServiceType }); } - /// - /// Queue an error chat message. While method is named as PrintChat (it calls it internally), it only add a entry to - /// the queue, later to be processed when UpdateQueue() is called. - /// - /// A message to send. + /// public void PrintError(string message) { // Log.Verbose("[CHATGUI PRINT REGULAR ERROR]{0}", message); @@ -194,11 +132,7 @@ public sealed class ChatGui : IDisposable, IServiceType }); } - /// - /// Queue an error chat message. While method is named as PrintChat (it calls it internally), it only add a entry to - /// the queue, later to be processed when UpdateQueue() is called. - /// - /// A message to send. + /// public void PrintError(SeString message) { // Log.Verbose("[CHATGUI PRINT SESTRING ERROR]{0}", message.TextValue); @@ -330,7 +264,7 @@ public sealed class ChatGui : IDisposable, IServiceType { try { - var messageHandledDelegate = @delegate as OnCheckMessageHandledDelegate; + var messageHandledDelegate = @delegate as IChatGui.OnCheckMessageHandledDelegate; messageHandledDelegate!.Invoke(chattype, senderid, ref parsedSender, ref parsedMessage, ref isHandled); } catch (Exception e) @@ -346,7 +280,7 @@ public sealed class ChatGui : IDisposable, IServiceType { try { - var messageHandledDelegate = @delegate as OnMessageDelegate; + var messageHandledDelegate = @delegate as IChatGui.OnMessageDelegate; messageHandledDelegate!.Invoke(chattype, senderid, ref parsedSender, ref parsedMessage, ref isHandled); } catch (Exception e) diff --git a/Dalamud/Plugin/Services/IChatGui.cs b/Dalamud/Plugin/Services/IChatGui.cs new file mode 100644 index 000000000..1d71bb886 --- /dev/null +++ b/Dalamud/Plugin/Services/IChatGui.cs @@ -0,0 +1,119 @@ +using Dalamud.Game.Gui; +using Dalamud.Game.Text; +using Dalamud.Game.Text.SeStringHandling; + +namespace Dalamud.Plugin.Services; + +/// +/// This class handles interacting with the native chat UI. +/// +public interface IChatGui +{ + /// + /// A delegate type used with the event. + /// + /// The type of chat. + /// The sender ID. + /// The sender name. + /// The message sent. + /// A value indicating whether the message was handled or should be propagated. + public delegate void OnMessageDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled); + + /// + /// A delegate type used with the event. + /// + /// The type of chat. + /// The sender ID. + /// The sender name. + /// The message sent. + /// A value indicating whether the message was handled or should be propagated. + public delegate void OnCheckMessageHandledDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled); + + /// + /// A delegate type used with the event. + /// + /// The type of chat. + /// The sender ID. + /// The sender name. + /// The message sent. + public delegate void OnMessageHandledDelegate(XivChatType type, uint senderId, SeString sender, SeString message); + + /// + /// A delegate type used with the event. + /// + /// The type of chat. + /// The sender ID. + /// The sender name. + /// The message sent. + public delegate void OnMessageUnhandledDelegate(XivChatType type, uint senderId, SeString sender, SeString message); + + /// + /// Event that will be fired when a chat message is sent to chat by the game. + /// + public event OnMessageDelegate ChatMessage; + + /// + /// Event that allows you to stop messages from appearing in chat by setting the isHandled parameter to true. + /// + public event OnCheckMessageHandledDelegate CheckMessageHandled; + + /// + /// Event that will be fired when a chat message is handled by Dalamud or a Plugin. + /// + public event OnMessageHandledDelegate ChatMessageHandled; + + /// + /// Event that will be fired when a chat message is not handled by Dalamud or a Plugin. + /// + public event OnMessageUnhandledDelegate ChatMessageUnhandled; + + /// + /// Gets the ID of the last linked item. + /// + public int LastLinkedItemId { get; } + + /// + /// Gets the flags of the last linked item. + /// + public byte LastLinkedItemFlags { get; } + + /// + /// Queue a chat message. While method is named as PrintChat, it only add a entry to the queue, + /// later to be processed when UpdateQueue() is called. + /// + /// A message to send. + public void PrintChat(XivChatEntry chat); + + /// + /// Queue a chat message. While method is named as PrintChat (it calls it internally), it only add a entry to the queue, + /// later to be processed when UpdateQueue() is called. + /// + /// A message to send. + public void Print(string message); + + /// + /// Queue a chat message. While method is named as PrintChat (it calls it internally), it only add a entry to the queue, + /// later to be processed when UpdateQueue() is called. + /// + /// A message to send. + public void Print(SeString message); + + /// + /// Queue an error chat message. While method is named as PrintChat (it calls it internally), it only add a entry to + /// the queue, later to be processed when UpdateQueue() is called. + /// + /// A message to send. + public void PrintError(string message); + + /// + /// Queue an error chat message. While method is named as PrintChat (it calls it internally), it only add a entry to + /// the queue, later to be processed when UpdateQueue() is called. + /// + /// A message to send. + public void PrintError(SeString message); + + /// + /// Process a chat queue. + /// + public void UpdateQueue(); +} From 7080087e9db6469b7ff824fab28d6e7cca6822a4 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Wed, 13 Sep 2023 19:06:28 -0700 Subject: [PATCH 053/120] Scope ChatGui --- Dalamud/Game/ChatHandlers.cs | 4 +- Dalamud/Game/Gui/ChatGui.cs | 224 +++++++++++++++++------ Dalamud/Plugin/Internal/PluginManager.cs | 4 +- Dalamud/Plugin/Services/IChatGui.cs | 38 ++-- 4 files changed, 186 insertions(+), 84 deletions(-) diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index ed69b7bbe..1d82e5f9c 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -264,7 +264,7 @@ public class ChatHandlers : IServiceType if (string.IsNullOrEmpty(this.configuration.LastVersion) || !assemblyVersion.StartsWith(this.configuration.LastVersion)) { - chatGui.PrintChat(new XivChatEntry + chatGui.Print(new XivChatEntry { Message = Loc.Localize("DalamudUpdated", "Dalamud has been updated successfully! Please check the discord for a full changelog."), Type = XivChatType.Notice, @@ -321,7 +321,7 @@ public class ChatHandlers : IServiceType } else { - chatGui.PrintChat(new XivChatEntry + chatGui.Print(new XivChatEntry { Message = new SeString(new List() { diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs index d8154b41d..2fbeb404e 100644 --- a/Dalamud/Game/Gui/ChatGui.cs +++ b/Dalamud/Game/Gui/ChatGui.cs @@ -20,13 +20,9 @@ namespace Dalamud.Game.Gui; /// /// This class handles interacting with the native chat UI. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -public sealed class ChatGui : IDisposable, IServiceType, IChatGui +internal sealed class ChatGui : IDisposable, IServiceType, IChatGui { private readonly ChatGuiAddressResolver address; @@ -66,16 +62,16 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui private delegate void InteractableLinkClickedDelegate(IntPtr managerPtr, IntPtr messagePtr); /// - public event IChatGui.OnMessageDelegate ChatMessage; + public event IChatGui.OnMessageDelegate? ChatMessage; /// - public event IChatGui.OnCheckMessageHandledDelegate CheckMessageHandled; + public event IChatGui.OnCheckMessageHandledDelegate? CheckMessageHandled; /// - public event IChatGui.OnMessageHandledDelegate ChatMessageHandled; + public event IChatGui.OnMessageHandledDelegate? ChatMessageHandled; /// - public event IChatGui.OnMessageUnhandledDelegate ChatMessageUnhandled; + public event IChatGui.OnMessageUnhandledDelegate? ChatMessageUnhandled; /// public int LastLinkedItemId { get; private set; } @@ -94,55 +90,35 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui } /// - public void PrintChat(XivChatEntry chat) + public void Print(XivChatEntry chat) { this.chatQueue.Enqueue(chat); } - + /// - public void Print(string message) + public void Print(string message, string? messageTag = null, ushort? tagColor = null) { - // Log.Verbose("[CHATGUI PRINT REGULAR]{0}", message); - this.PrintChat(new XivChatEntry - { - Message = message, - Type = this.configuration.GeneralChatType, - }); + this.PrintTagged(message, this.configuration.GeneralChatType, messageTag, tagColor); } - + /// - public void Print(SeString message) + public void Print(SeString message, string? messageTag = null, ushort? tagColor = null) { - // Log.Verbose("[CHATGUI PRINT SESTRING]{0}", message.TextValue); - this.PrintChat(new XivChatEntry - { - Message = message, - Type = this.configuration.GeneralChatType, - }); + this.PrintTagged(message, this.configuration.GeneralChatType, messageTag, tagColor); } - + /// - public void PrintError(string message) + public void PrintError(string message, string? messageTag = null, ushort? tagColor = null) { - // Log.Verbose("[CHATGUI PRINT REGULAR ERROR]{0}", message); - this.PrintChat(new XivChatEntry - { - Message = message, - Type = XivChatType.Urgent, - }); + this.PrintTagged(message, XivChatType.Urgent, messageTag, tagColor); } - + /// - public void PrintError(SeString message) + public void PrintError(SeString message, string? messageTag = null, ushort? tagColor = null) { - // Log.Verbose("[CHATGUI PRINT SESTRING ERROR]{0}", message.TextValue); - this.PrintChat(new XivChatEntry - { - Message = message, - Type = XivChatType.Urgent, - }); + this.PrintTagged(message, XivChatType.Urgent, messageTag, tagColor); } - + /// /// Process a chat queue. /// @@ -176,7 +152,7 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui /// A payload for handling. internal DalamudLinkPayload AddChatLinkHandler(string pluginName, uint commandId, Action commandAction) { - var payload = new DalamudLinkPayload() { Plugin = pluginName, CommandId = commandId }; + var payload = new DalamudLinkPayload { Plugin = pluginName, CommandId = commandId }; this.dalamudLinkHandlers.Add((pluginName, commandId), commandAction); return payload; } @@ -200,20 +176,63 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui /// The ID of the command to be removed. internal void RemoveChatLinkHandler(string pluginName, uint commandId) { - if (this.dalamudLinkHandlers.ContainsKey((pluginName, commandId))) - { - this.dalamudLinkHandlers.Remove((pluginName, commandId)); - } + this.dalamudLinkHandlers.Remove((pluginName, commandId)); } [ServiceManager.CallWhenServicesReady] - private void ContinueConstruction(GameGui gameGui, LibcFunction libcFunction) + private void ContinueConstruction() { this.printMessageHook.Enable(); this.populateItemLinkHook.Enable(); this.interactableLinkClickedHook.Enable(); } + private void PrintTagged(string message, XivChatType channel, string? tag, ushort? color) + { + var builder = new SeStringBuilder(); + + if (!tag.IsNullOrEmpty()) + { + if (color is not null) + { + builder.AddUiForeground($"[{tag}] ", color.Value); + } + else + { + builder.AddText($"[{tag}] "); + } + } + + this.Print(new XivChatEntry + { + Message = builder.AddText(message).Build(), + Type = channel, + }); + } + + private void PrintTagged(SeString message, XivChatType channel, string? tag, ushort? color) + { + var builder = new SeStringBuilder(); + + if (!tag.IsNullOrEmpty()) + { + if (color is not null) + { + builder.AddUiForeground($"[{tag}] ", color.Value); + } + else + { + builder.AddText($"[{tag}] "); + } + } + + this.Print(new XivChatEntry + { + Message = builder.Build().Append(message), + Type = channel, + }); + } + private void HandlePopulateItemLinkDetour(IntPtr linkObjectPtr, IntPtr itemInfoPtr) { try @@ -232,7 +251,7 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui } } - private IntPtr HandlePrintMessageDetour(IntPtr manager, XivChatType chattype, IntPtr pSenderName, IntPtr pMessage, uint senderid, IntPtr parameter) + private IntPtr HandlePrintMessageDetour(IntPtr manager, XivChatType chatType, IntPtr pSenderName, IntPtr pMessage, uint senderId, IntPtr parameter) { var retVal = IntPtr.Zero; @@ -259,13 +278,13 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui // Call events var isHandled = false; - var invocationList = this.CheckMessageHandled.GetInvocationList(); + var invocationList = this.CheckMessageHandled!.GetInvocationList(); foreach (var @delegate in invocationList) { try { var messageHandledDelegate = @delegate as IChatGui.OnCheckMessageHandledDelegate; - messageHandledDelegate!.Invoke(chattype, senderid, ref parsedSender, ref parsedMessage, ref isHandled); + messageHandledDelegate!.Invoke(chatType, senderId, ref parsedSender, ref parsedMessage, ref isHandled); } catch (Exception e) { @@ -275,13 +294,13 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui if (!isHandled) { - invocationList = this.ChatMessage.GetInvocationList(); + invocationList = this.ChatMessage!.GetInvocationList(); foreach (var @delegate in invocationList) { try { var messageHandledDelegate = @delegate as IChatGui.OnMessageDelegate; - messageHandledDelegate!.Invoke(chattype, senderid, ref parsedSender, ref parsedMessage, ref isHandled); + messageHandledDelegate!.Invoke(chatType, senderId, ref parsedSender, ref parsedMessage, ref isHandled); } catch (Exception e) { @@ -324,12 +343,12 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui // Print the original chat if it's handled. if (isHandled) { - this.ChatMessageHandled?.Invoke(chattype, senderid, parsedSender, parsedMessage); + this.ChatMessageHandled?.Invoke(chatType, senderId, parsedSender, parsedMessage); } else { - retVal = this.printMessageHook.Original(manager, chattype, senderPtr, messagePtr, senderid, parameter); - this.ChatMessageUnhandled?.Invoke(chattype, senderid, parsedSender, parsedMessage); + retVal = this.printMessageHook.Original(manager, chatType, senderPtr, messagePtr, senderId, parameter); + this.ChatMessageUnhandled?.Invoke(chatType, senderId, parsedSender, parsedMessage); } if (this.baseAddress == IntPtr.Zero) @@ -341,7 +360,7 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui catch (Exception ex) { Log.Error(ex, "Exception on OnChatMessage hook."); - retVal = this.printMessageHook.Original(manager, chattype, pSenderName, pMessage, senderid, parameter); + retVal = this.printMessageHook.Original(manager, chatType, pSenderName, pMessage, senderId, parameter); } return retVal; @@ -373,10 +392,10 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui var linkPayload = payloads[0]; if (linkPayload is DalamudLinkPayload link) { - if (this.dalamudLinkHandlers.ContainsKey((link.Plugin, link.CommandId))) + if (this.dalamudLinkHandlers.TryGetValue((link.Plugin, link.CommandId), out var value)) { Log.Verbose($"Sending DalamudLink to {link.Plugin}: {link.CommandId}"); - this.dalamudLinkHandlers[(link.Plugin, link.CommandId)].Invoke(link.CommandId, new SeString(payloads)); + value.Invoke(link.CommandId, new SeString(payloads)); } else { @@ -390,3 +409,88 @@ public sealed class ChatGui : IDisposable, IServiceType, IChatGui } } } + +/// +/// Plugin scoped version of ChatGui. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class ChatGuiPluginScoped : IDisposable, IServiceType, IChatGui +{ + [ServiceManager.ServiceDependency] + private readonly ChatGui chatGuiService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal ChatGuiPluginScoped() + { + this.chatGuiService.ChatMessage += this.OnMessageForward; + this.chatGuiService.CheckMessageHandled += this.OnCheckMessageForward; + this.chatGuiService.ChatMessageHandled += this.OnMessageHandledForward; + this.chatGuiService.ChatMessageUnhandled += this.OnMessageUnhandledForward; + } + + /// + public event IChatGui.OnMessageDelegate? ChatMessage; + + /// + public event IChatGui.OnCheckMessageHandledDelegate? CheckMessageHandled; + + /// + public event IChatGui.OnMessageHandledDelegate? ChatMessageHandled; + + /// + public event IChatGui.OnMessageUnhandledDelegate? ChatMessageUnhandled; + + /// + public int LastLinkedItemId => this.chatGuiService.LastLinkedItemId; + + /// + public byte LastLinkedItemFlags => this.chatGuiService.LastLinkedItemFlags; + + /// + public void Dispose() + { + this.chatGuiService.ChatMessage -= this.OnMessageForward; + this.chatGuiService.CheckMessageHandled -= this.OnCheckMessageForward; + this.chatGuiService.ChatMessageHandled -= this.OnMessageHandledForward; + this.chatGuiService.ChatMessageUnhandled -= this.OnMessageUnhandledForward; + } + + /// + public void Print(XivChatEntry chat) + => this.chatGuiService.Print(chat); + + /// + public void Print(string message, string? messageTag = null, ushort? tagColor = null) + => this.chatGuiService.Print(message, messageTag, tagColor); + + /// + public void Print(SeString message, string? messageTag = null, ushort? tagColor = null) + => this.chatGuiService.Print(message, messageTag, tagColor); + + /// + public void PrintError(string message, string? messageTag = null, ushort? tagColor = null) + => this.chatGuiService.PrintError(message, messageTag, tagColor); + + /// + public void PrintError(SeString message, string? messageTag = null, ushort? tagColor = null) + => this.chatGuiService.PrintError(message, messageTag, tagColor); + + private void OnMessageForward(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) + => this.ChatMessage?.Invoke(type, senderId, ref sender, ref message, ref isHandled); + + private void OnCheckMessageForward(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) + => this.CheckMessageHandled?.Invoke(type, senderId, ref sender, ref message, ref isHandled); + + private void OnMessageHandledForward(XivChatType type, uint senderId, SeString sender, SeString message) + => this.ChatMessageHandled?.Invoke(type, senderId, sender, message); + + private void OnMessageUnhandledForward(XivChatType type, uint senderId, SeString sender, SeString message) + => this.ChatMessageUnhandled?.Invoke(type, senderId, sender, message); +} diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index b160038d7..691d5f729 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -285,7 +285,7 @@ internal partial class PluginManager : IDisposable, IServiceType if (updateMetadata is { Count: > 0 }) { - chatGui.PrintChat(new XivChatEntry + chatGui.Print(new XivChatEntry { Message = new SeString(new List() { @@ -308,7 +308,7 @@ internal partial class PluginManager : IDisposable, IServiceType } else { - chatGui.PrintChat(new XivChatEntry + chatGui.Print(new XivChatEntry { Message = Locs.DalamudPluginUpdateFailed(metadata.Name, metadata.Version), Type = XivChatType.Urgent, diff --git a/Dalamud/Plugin/Services/IChatGui.cs b/Dalamud/Plugin/Services/IChatGui.cs index 1d71bb886..bafdabbb5 100644 --- a/Dalamud/Plugin/Services/IChatGui.cs +++ b/Dalamud/Plugin/Services/IChatGui.cs @@ -78,42 +78,40 @@ public interface IChatGui public byte LastLinkedItemFlags { get; } /// - /// Queue a chat message. While method is named as PrintChat, it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. + /// Queue a chat message. Dalamud will send queued messages on the next framework event. /// /// A message to send. - public void PrintChat(XivChatEntry chat); + public void Print(XivChatEntry chat); /// - /// Queue a chat message. While method is named as PrintChat (it calls it internally), it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. + /// Queue a chat message. Dalamud will send queued messages on the next framework event. /// /// A message to send. - public void Print(string message); + /// String to prepend message with "[messageTag] ". + /// Color to display the message tag with. + public void Print(string message, string? messageTag = null, ushort? tagColor = null); /// - /// Queue a chat message. While method is named as PrintChat (it calls it internally), it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. + /// Queue a chat message. Dalamud will send queued messages on the next framework event. /// /// A message to send. - public void Print(SeString message); + /// String to prepend message with "[messageTag] ". + /// Color to display the message tag with. + public void Print(SeString message, string? messageTag = null, ushort? tagColor = null); /// - /// Queue an error chat message. While method is named as PrintChat (it calls it internally), it only add a entry to - /// the queue, later to be processed when UpdateQueue() is called. + /// Queue a chat message. Dalamud will send queued messages on the next framework event. /// /// A message to send. - public void PrintError(string message); + /// String to prepend message with "[messageTag] ". + /// Color to display the message tag with. + public void PrintError(string message, string? messageTag = null, ushort? tagColor = null); /// - /// Queue an error chat message. While method is named as PrintChat (it calls it internally), it only add a entry to - /// the queue, later to be processed when UpdateQueue() is called. + /// Queue a chat message. Dalamud will send queued messages on the next framework event. /// /// A message to send. - public void PrintError(SeString message); - - /// - /// Process a chat queue. - /// - public void UpdateQueue(); + /// String to prepend message with "[messageTag] ". + /// Color to display the message tag with. + public void PrintError(SeString message, string? messageTag = null, ushort? tagColor = null); } From 947cd79bcae588ed30c0ea36b62b5e61ecace971 Mon Sep 17 00:00:00 2001 From: kal <35899782+kalilistic@users.noreply.github.com> Date: Sat, 16 Sep 2023 20:54:29 -0400 Subject: [PATCH 054/120] chore: remove remaining obsolete icons --- .../Interface/FontAwesome/FontAwesomeIcon.cs | 62 +++---------------- 1 file changed, 10 insertions(+), 52 deletions(-) diff --git a/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs b/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs index 3d21ea86c..f88d7f8f0 100644 --- a/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs +++ b/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Generated by Dalamud.FASharpGen - don't modify this file directly. -// Font-Awesome Version: 6.3.0 +// Font-Awesome Version: 6.4.2 // //------------------------------------------------------------------------------ @@ -19,12 +19,6 @@ public enum FontAwesomeIcon /// None = 0, - /// - /// The Font Awesome "acquisitionsincorporated" icon unicode character. - /// - [Obsolete] - AcquisitionsIncorporated = 0xF6AF, - /// /// The Font Awesome "rectangle-ad" icon unicode character. /// @@ -43,7 +37,7 @@ public enum FontAwesomeIcon /// The Font Awesome "address-card" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "address card", "about", "contact", "id", "identification", "postcard", "profile", "registration" })] - [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Users + People" })] + [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Alphabet", "Business", "Communication", "Users + People" })] AddressCard = 0xF2BB, /// @@ -53,12 +47,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams", "Design", "Editing", "Photos + Images", "Shapes" })] Adjust = 0xF042, - /// - /// The Font Awesome "adobe" icon unicode character. - /// - [Obsolete] - Adobe = 0xF778, - /// /// The Font Awesome "spray-can-sparkles" icon unicode character. /// @@ -884,7 +872,7 @@ public enum FontAwesomeIcon /// The Font Awesome "binoculars" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "binoculars", "glasses", "magnify", "scenic", "spyglass", "view" })] - [FontAwesomeCategoriesAttribute(new[] { "Camping", "Maps", "Nature" })] + [FontAwesomeCategoriesAttribute(new[] { "Astronomy", "Camping", "Maps", "Nature" })] Binoculars = 0xF1E5, /// @@ -1359,7 +1347,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bullseye" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bullseye", "archery", "goal", "objective", "target" })] + [FontAwesomeSearchTerms(new[] { "bullseye", "archery", "goal", "objective", "strategy", "target" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Marketing", "Toggle" })] Bullseye = 0xF140, @@ -2202,7 +2190,7 @@ public enum FontAwesomeIcon /// The Font Awesome "gear" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "cog", "cogwheel", "gear", "mechanical", "settings", "sprocket", "tool", "wheel" })] - [FontAwesomeCategoriesAttribute(new[] { "Spinners" })] + [FontAwesomeCategoriesAttribute(new[] { "Coding", "Editing", "Spinners" })] Cog = 0xF013, /// @@ -3423,14 +3411,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "flask" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "flask", "beaker", "experimental", "labs", "science" })] + [FontAwesomeSearchTerms(new[] { "flask", "beaker", "chemicals", "experiment", "experimental", "labs", "liquid", "potion", "science", "vial" })] [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Maps", "Medical + Health", "Science" })] Flask = 0xF0C3, /// /// The Font Awesome "flask-vial" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "flask vial", "ampule", "chemistry", "lab", "laboratory", "test", "test tube" })] + [FontAwesomeSearchTerms(new[] { "flask vial", " beaker", " chemicals", " experiment", " experimental", " labs", " liquid", " science", " vial", "ampule", "chemistry", "lab", "laboratory", "potion", "test", "test tube" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Science" })] FlaskVial = 0xE4F3, @@ -5088,7 +5076,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "lightbulb" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "lightbulb", "bulb", "comic", "electric", "energy", "idea", "inspiration", "light", "light bulb" })] + [FontAwesomeSearchTerms(new[] { "lightbulb", " comic", " electric", " idea", " innovation", " inspiration", " light", " light bulb", " bulb", "bulb", "comic", "electric", "energy", "idea", "inspiration", "mechanical" })] [FontAwesomeCategoriesAttribute(new[] { "Energy", "Household", "Maps", "Marketing" })] Lightbulb = 0xF0EB, @@ -5270,7 +5258,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "magnifying-glass-chart" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass chart", "analysis", "chart" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass chart", " data", " graph", " intelligence", "analysis", "chart", "market" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Humanitarian", "Marketing" })] MagnifyingGlassChart = 0xE522, @@ -5484,12 +5472,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Astronomy", "Weather" })] Meteor = 0xF753, - /// - /// The Font Awesome "microblog" icon unicode character. - /// - [Obsolete] - Microblog = 0xF91A, - /// /// The Font Awesome "microchip" icon unicode character. /// @@ -5676,7 +5658,7 @@ public enum FontAwesomeIcon /// The Font Awesome "monument" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "monument", "building", "historic", "landmark", "memorable" })] - [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Travel + Hotel" })] + [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Maps", "Travel + Hotel" })] Monument = 0xF5A6, /// @@ -6043,12 +6025,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing" })] PenNib = 0xF5AD, - /// - /// The Font Awesome "pennyarcade" icon unicode character. - /// - [Obsolete] - PennyArcade = 0xF704, - /// /// The Font Awesome "square-pen" icon unicode character. /// @@ -6415,12 +6391,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Files", "Film + Video", "Photos + Images", "Social" })] PhotoVideo = 0xF87C, - /// - /// The Font Awesome "piedpipersquare" icon unicode character. - /// - [Obsolete] - PiedPiperSquare = 0xF91E, - /// /// The Font Awesome "piggy-bank" icon unicode character. /// @@ -8720,12 +8690,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Travel + Hotel" })] TreeCity = 0xE587, - /// - /// The Font Awesome "tripadvisor" icon unicode character. - /// - [Obsolete] - Tripadvisor = 0xF262, - /// /// The Font Awesome "trophy" icon unicode character. /// @@ -8887,12 +8851,6 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] UndoAlt = 0xF2EA, - /// - /// The Font Awesome "unity" icon unicode character. - /// - [Obsolete] - Unity = 0xF949, - /// /// The Font Awesome "universal-access" icon unicode character. /// From 85bb5229d9c4b8bc84d1bc1fbd85b574ba59cc25 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Sat, 16 Sep 2023 18:00:08 -0700 Subject: [PATCH 055/120] Update ClientStructs - Fix build errors caused by obsoletes --- Dalamud/Game/ClientState/Objects/SubKinds/BattleNpc.cs | 4 +--- .../Game/ClientState/Objects/SubKinds/PlayerCharacter.cs | 4 +--- Dalamud/Game/ClientState/Objects/Types/Character.cs | 7 +++---- lib/FFXIVClientStructs | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Dalamud/Game/ClientState/Objects/SubKinds/BattleNpc.cs b/Dalamud/Game/ClientState/Objects/SubKinds/BattleNpc.cs index 59f32e33d..add7a7f9f 100644 --- a/Dalamud/Game/ClientState/Objects/SubKinds/BattleNpc.cs +++ b/Dalamud/Game/ClientState/Objects/SubKinds/BattleNpc.cs @@ -1,5 +1,3 @@ -using System; - using Dalamud.Game.ClientState.Objects.Enums; namespace Dalamud.Game.ClientState.Objects.Types; @@ -25,5 +23,5 @@ public unsafe class BattleNpc : BattleChara public BattleNpcSubKind BattleNpcKind => (BattleNpcSubKind)this.Struct->Character.GameObject.SubKind; /// - public override ulong TargetObjectId => this.Struct->Character.TargetObjectID; + public override ulong TargetObjectId => this.Struct->Character.TargetId; } diff --git a/Dalamud/Game/ClientState/Objects/SubKinds/PlayerCharacter.cs b/Dalamud/Game/ClientState/Objects/SubKinds/PlayerCharacter.cs index 7fc9c0079..9de11e3ec 100644 --- a/Dalamud/Game/ClientState/Objects/SubKinds/PlayerCharacter.cs +++ b/Dalamud/Game/ClientState/Objects/SubKinds/PlayerCharacter.cs @@ -1,5 +1,3 @@ -using System; - using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Resolvers; @@ -33,5 +31,5 @@ public unsafe class PlayerCharacter : BattleChara /// /// Gets the target actor ID of the PlayerCharacter. /// - public override ulong TargetObjectId => this.Struct->Character.PlayerTargetObjectID; + public override ulong TargetObjectId => this.Struct->Character.LookTargetId; } diff --git a/Dalamud/Game/ClientState/Objects/Types/Character.cs b/Dalamud/Game/ClientState/Objects/Types/Character.cs index ee8418362..a1eb52edc 100644 --- a/Dalamud/Game/ClientState/Objects/Types/Character.cs +++ b/Dalamud/Game/ClientState/Objects/Types/Character.cs @@ -1,5 +1,3 @@ -using System; - using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Resolvers; using Dalamud.Game.Text.SeStringHandling; @@ -87,7 +85,7 @@ public unsafe class Character : GameObject /// /// Gets the target object ID of the character. /// - public override ulong TargetObjectId => this.Struct->TargetObjectID; + public override ulong TargetObjectId => this.Struct->TargetId; /// /// Gets the name ID of the character. @@ -115,5 +113,6 @@ public unsafe class Character : GameObject /// /// Gets the underlying structure. /// - protected internal new FFXIVClientStructs.FFXIV.Client.Game.Character.Character* Struct => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)this.Address; + protected internal new FFXIVClientStructs.FFXIV.Client.Game.Character.Character* Struct => + (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)this.Address; } diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index 7279a8f3c..06e3ca233 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit 7279a8f3ca6b79490184b05532af509781a89415 +Subproject commit 06e3ca2336031ba86ef95d022a2af722e5d00a7e From a9a0980372c3cecc405daa952c5cb2da9420b064 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Sat, 16 Sep 2023 18:07:19 -0700 Subject: [PATCH 056/120] Fix random build warnings. --- .../Game/Gui/PartyFinder/PartyFinderGui.cs | 5 ++- Dalamud/Interface/ColorHelpers.cs | 39 ++++++++++++------- Dalamud/Plugin/Services/IPluginLog.cs | 6 +-- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs index 85c6a4a39..e3ea74f2d 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs @@ -1,6 +1,4 @@ -using System; using System.Runtime.InteropServices; - using Dalamud.Game.Gui.PartyFinder.Internal; using Dalamud.Game.Gui.PartyFinder.Types; using Dalamud.Hooking; @@ -128,6 +126,9 @@ internal sealed class PartyFinderGui : IDisposable, IServiceType, IPartyFinderGu } } +/// +/// A scoped variant of the PartyFinderGui service. +/// [PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.ScopedService] diff --git a/Dalamud/Interface/ColorHelpers.cs b/Dalamud/Interface/ColorHelpers.cs index 71f959292..ad9eedaa9 100644 --- a/Dalamud/Interface/ColorHelpers.cs +++ b/Dalamud/Interface/ColorHelpers.cs @@ -1,4 +1,4 @@ -using System; +using System.Diagnostics.CodeAnalysis; using System.Numerics; namespace Dalamud.Interface; @@ -8,6 +8,17 @@ namespace Dalamud.Interface; /// public static class ColorHelpers { + /// + /// A struct representing a color using HSVA coordinates. + /// + /// The hue represented by this struct. + /// The saturation represented by this struct. + /// The value represented by this struct. + /// The alpha represented by this struct. + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", + Justification = "I don't like it.")] + public record struct HsvaColor(float H, float S, float V, float A); + /// /// Pack a vector4 color into a uint for use in ImGui APIs. /// @@ -22,7 +33,7 @@ public static class ColorHelpers return (uint)((a << 24) | (b << 16) | (g << 8) | r); } - + /// /// Convert a RGBA color in the range of 0.f to 1.f to a uint. /// @@ -37,7 +48,7 @@ public static class ColorHelpers return new Vector4(r, g, b, a); } - + /// /// Convert a RGBA color in the range of 0.f to 1.f to a HSV color. /// @@ -146,7 +157,7 @@ public static class ColorHelpers return new Vector4(r, g, b, hsv.A); } - + /// /// Lighten a color. /// @@ -159,7 +170,7 @@ public static class ColorHelpers hsv.V += amount; return HsvToRgb(hsv); } - + /// /// Lighten a color. /// @@ -168,7 +179,7 @@ public static class ColorHelpers /// The lightened color. public static uint Lighten(uint color, float amount) => RgbaVector4ToUint(Lighten(RgbaUintToVector4(color), amount)); - + /// /// Darken a color. /// @@ -181,7 +192,7 @@ public static class ColorHelpers hsv.V -= amount; return HsvToRgb(hsv); } - + /// /// Darken a color. /// @@ -190,7 +201,7 @@ public static class ColorHelpers /// The darkened color. public static uint Darken(uint color, float amount) => RgbaVector4ToUint(Darken(RgbaUintToVector4(color), amount)); - + /// /// Saturate a color. /// @@ -203,7 +214,7 @@ public static class ColorHelpers hsv.S += amount; return HsvToRgb(hsv); } - + /// /// Saturate a color. /// @@ -212,7 +223,7 @@ public static class ColorHelpers /// The saturated color. public static uint Saturate(uint color, float amount) => RgbaVector4ToUint(Saturate(RgbaUintToVector4(color), amount)); - + /// /// Desaturate a color. /// @@ -225,7 +236,7 @@ public static class ColorHelpers hsv.S -= amount; return HsvToRgb(hsv); } - + /// /// Desaturate a color. /// @@ -234,7 +245,7 @@ public static class ColorHelpers /// The desaturated color. public static uint Desaturate(uint color, float amount) => RgbaVector4ToUint(Desaturate(RgbaUintToVector4(color), amount)); - + /// /// Fade a color. /// @@ -247,7 +258,7 @@ public static class ColorHelpers hsv.A -= amount; return HsvToRgb(hsv); } - + /// /// Fade a color. /// @@ -256,6 +267,4 @@ public static class ColorHelpers /// The faded color. public static uint Fade(uint color, float amount) => RgbaVector4ToUint(Fade(RgbaUintToVector4(color), amount)); - - public record struct HsvaColor(float H, float S, float V, float A); } diff --git a/Dalamud/Plugin/Services/IPluginLog.cs b/Dalamud/Plugin/Services/IPluginLog.cs index 87876f36f..62f9e8728 100644 --- a/Dalamud/Plugin/Services/IPluginLog.cs +++ b/Dalamud/Plugin/Services/IPluginLog.cs @@ -1,8 +1,8 @@ -using System; - -using Serilog; +using Serilog; using Serilog.Events; +#pragma warning disable CS1573 // See https://github.com/dotnet/roslyn/issues/40325 + namespace Dalamud.Plugin.Services; /// From 57ae2264e3461ba9d4367527fc39586391619d4e Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Sat, 16 Sep 2023 18:11:06 -0700 Subject: [PATCH 057/120] Fix SA1502 errors on autoformat - Braces in `{ }` style cause SA1502 to complain. --- .editorconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index 0e4f800e0..0ae30cf95 100644 --- a/.editorconfig +++ b/.editorconfig @@ -57,12 +57,12 @@ dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static,readonly -dotnet_style_parentheses_in_arithmetic_binary_operators =always_for_clarity:suggestion -dotnet_style_parentheses_in_other_binary_operators =always_for_clarity:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion -dotnet_style_parentheses_in_other_operators=always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = always_for_clarity:silent dotnet_style_object_initializer = false dotnet_style_qualification_for_event = true:suggestion dotnet_style_qualification_for_field = true:suggestion @@ -78,7 +78,7 @@ csharp_space_before_comma = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_after_comma = true csharp_space_after_cast = false -csharp_space_around_binary_operators = before_and_after +csharp_space_around_binary_operators = before_and_after csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_parentheses = none @@ -101,7 +101,7 @@ resharper_braces_for_ifelse = required_for_multiline resharper_can_use_global_alias = false resharper_csharp_align_multiline_parameter = true resharper_csharp_align_multiple_declaration = true -resharper_csharp_empty_block_style = together_same_line +resharper_csharp_empty_block_style = multiline resharper_csharp_int_align_comments = true resharper_csharp_new_line_before_while = true resharper_csharp_wrap_after_declaration_lpar = true @@ -133,13 +133,13 @@ resharper_suggest_var_or_type_built_in_types_highlighting = hint resharper_suggest_var_or_type_elsewhere_highlighting = hint resharper_suggest_var_or_type_simple_types_highlighting = hint resharper_unused_auto_property_accessor_global_highlighting = none -csharp_style_deconstructed_variable_declaration=true:silent +csharp_style_deconstructed_variable_declaration = true:silent [*.{appxmanifest,asax,ascx,aspx,axaml,axml,build,c,c++,cc,cginc,compute,config,cp,cpp,cs,cshtml,csproj,css,cu,cuh,cxx,dbml,discomap,dtd,h,hh,hlsl,hlsli,hlslinc,hpp,htm,html,hxx,inc,inl,ino,ipp,js,json,jsproj,jsx,lsproj,master,mpp,mq4,mq5,mqh,njsproj,nuspec,paml,proj,props,proto,razor,resjson,resw,resx,skin,StyleCop,targets,tasks,tpp,ts,tsx,usf,ush,vb,vbproj,xaml,xamlx,xml,xoml,xsd}] indent_style = space indent_size = 4 tab_width = 4 -dotnet_style_parentheses_in_other_operators=always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = always_for_clarity:silent [*.{yaml,yml}] indent_style = space From 2c23e6fdb33db0dad89a3a93b02073f19d77169f Mon Sep 17 00:00:00 2001 From: KazWolfe Date: Sun, 17 Sep 2023 06:56:49 -0700 Subject: [PATCH 058/120] [v9] Move GPose check to ClientState (#1378) --- Dalamud/Game/ClientState/ClientState.cs | 3 +++ Dalamud/Interface/UiBuilder.cs | 18 +++--------------- Dalamud/Plugin/Services/IClientState.cs | 5 +++++ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index fed0ec3c4..6817523af 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -102,6 +102,9 @@ public sealed class ClientState : IDisposable, IServiceType, IClientState /// public bool IsPvPExcludingDen { get; private set; } + /// + public bool IsGPosing => GameMain.IsInGPose(); + /// /// Gets client state address resolver. /// diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs index b440a0705..95ee28f56 100644 --- a/Dalamud/Interface/UiBuilder.cs +++ b/Dalamud/Interface/UiBuilder.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Game; +using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.Gui; using Dalamud.Interface.GameFonts; @@ -179,20 +180,6 @@ public sealed class UiBuilder : IDisposable } } - /// - /// Gets a value indicating whether or not gpose is active. - /// - public bool GposeActive - { - get - { - var condition = Service.GetNullable(); - if (condition == null) - return false; - return condition[ConditionFlag.WatchingCutscene]; - } - } - /// /// Gets a value indicating whether this plugin should modify the game's interface at this time. /// @@ -448,6 +435,7 @@ public sealed class UiBuilder : IDisposable { this.hitchDetector.Start(); + var clientState = Service.Get(); var configuration = Service.Get(); var gameGui = Service.GetNullable(); if (gameGui == null) @@ -457,7 +445,7 @@ public sealed class UiBuilder : IDisposable !(this.DisableUserUiHide || this.DisableAutomaticUiHide)) || (this.CutsceneActive && configuration.ToggleUiHideDuringCutscenes && !(this.DisableCutsceneUiHide || this.DisableAutomaticUiHide)) || - (this.GposeActive && configuration.ToggleUiHideDuringGpose && + (clientState.IsGPosing && configuration.ToggleUiHideDuringGpose && !(this.DisableGposeUiHide || this.DisableAutomaticUiHide))) { if (!this.lastFrameUiHideState) diff --git a/Dalamud/Plugin/Services/IClientState.cs b/Dalamud/Plugin/Services/IClientState.cs index d66db9cc9..881cad841 100644 --- a/Dalamud/Plugin/Services/IClientState.cs +++ b/Dalamud/Plugin/Services/IClientState.cs @@ -73,4 +73,9 @@ public interface IClientState /// Gets a value indicating whether or not the user is playing PvP, excluding the Wolves' Den. /// public bool IsPvPExcludingDen { get; } + + /// + /// Gets a value indicating whether the client is currently in Group Pose (GPose) mode. + /// + public bool IsGPosing { get; } } From 428e1afefd8e7e9ace99eef506f009f82bb93213 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 17 Sep 2023 20:11:34 +0200 Subject: [PATCH 059/120] fix warnings --- Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs index e3ea74f2d..41a8ba56a 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; + using Dalamud.Game.Gui.PartyFinder.Internal; using Dalamud.Game.Gui.PartyFinder.Types; using Dalamud.Hooking; From ab9b7e1602192b0cfdf394d782dd1bd128ea3f9d Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 17 Sep 2023 20:35:40 +0200 Subject: [PATCH 060/120] chore: add data widget for servicecontainer status, remove serveropcode data widget --- .../Internal/Windows/Data/DataWindow.cs | 2 +- .../Data/Widgets/ServerOpcodeWidget.cs | 40 ------------- .../Windows/Data/Widgets/ServicesWidget.cs | 59 +++++++++++++++++++ Dalamud/IoC/Internal/ServiceContainer.cs | 10 ++++ 4 files changed, 70 insertions(+), 41 deletions(-) delete mode 100644 Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs create mode 100644 Dalamud/Interface/Internal/Windows/Data/Widgets/ServicesWidget.cs diff --git a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs index 4c446cacd..1363c6abe 100644 --- a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs +++ b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs @@ -19,7 +19,7 @@ internal class DataWindow : Window { private readonly IDataWindowWidget[] modules = { - new ServerOpcodeWidget(), + new ServicesWidget(), new AddressesWidget(), new ObjectTableWidget(), new FateTableWidget(), diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs deleted file mode 100644 index b23f3961e..000000000 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ServerOpcodeWidget.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Dalamud.Data; -using ImGuiNET; -using Newtonsoft.Json; - -namespace Dalamud.Interface.Internal.Windows.Data.Widgets; - -/// -/// Widget to display the currently set server opcodes. -/// -internal class ServerOpcodeWidget : IDataWindowWidget -{ - private string? serverOpString; - - /// - public string[]? CommandShortcuts { get; init; } = { "opcode", "serveropcode" }; - - /// - public string DisplayName { get; init; } = "Server Opcode"; - - /// - public bool Ready { get; set; } - - /// - public void Load() - { - var dataManager = Service.Get(); - - if (dataManager.IsDataReady) - { - this.serverOpString = JsonConvert.SerializeObject(dataManager.ServerOpCodes, Formatting.Indented); - this.Ready = true; - } - } - - /// - public void Draw() - { - ImGui.TextUnformatted(this.serverOpString ?? "serverOpString not initialized"); - } -} diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ServicesWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ServicesWidget.cs new file mode 100644 index 000000000..49f3c1b90 --- /dev/null +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ServicesWidget.cs @@ -0,0 +1,59 @@ +using System.Linq; + +using Dalamud.Interface.Colors; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; +using Dalamud.IoC.Internal; +using ImGuiNET; + +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; + +/// +/// Widget for displaying start info. +/// +internal class ServicesWidget : IDataWindowWidget +{ + /// + public string[]? CommandShortcuts { get; init; } = { "services" }; + + /// + public string DisplayName { get; init; } = "Service Container"; + + /// + public bool Ready { get; set; } + + /// + public void Load() + { + this.Ready = true; + } + + /// + public void Draw() + { + var container = Service.Get(); + + foreach (var instance in container.Instances) + { + var hasInterface = container.InterfaceToTypeMap.Values.Any(x => x == instance.Key); + var isPublic = instance.Key.IsPublic; + + ImGui.BulletText($"{instance.Key.FullName} ({instance.Key.GetServiceKind()})"); + + using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed, !hasInterface)) + { + ImGui.Text(hasInterface + ? $"\t => Provided via interface: {container.InterfaceToTypeMap.First(x => x.Value == instance.Key).Key.FullName}" + : "\t => NO INTERFACE!!!"); + } + + if (isPublic) + { + using var color = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed); + ImGui.Text("\t => PUBLIC!!!"); + } + + ImGuiHelpers.ScaledDummy(2); + } + } +} diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs index db748303e..a82440029 100644 --- a/Dalamud/IoC/Internal/ServiceContainer.cs +++ b/Dalamud/IoC/Internal/ServiceContainer.cs @@ -29,6 +29,16 @@ internal class ServiceContainer : IServiceProvider, IServiceType public ServiceContainer() { } + + /// + /// Gets a dictionary of all registered instances. + /// + public IReadOnlyDictionary Instances => this.instances; + + /// + /// Gets a dictionary mapping interfaces to their implementations. + /// + public IReadOnlyDictionary InterfaceToTypeMap => this.interfaceToTypeMap; /// /// Register a singleton object of any type into the current IOC container. From 5809cf5d7c30926f57e16c17466169897919d945 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 17 Sep 2023 21:09:00 +0200 Subject: [PATCH 061/120] chore: make all services with interfaces internal --- Dalamud/Data/DataManager.cs | 2 +- Dalamud/Game/BaseAddressResolver.cs | 2 +- .../Game/ClientState/Aetherytes/AetheryteList.cs | 4 ++-- Dalamud/Game/ClientState/Buddy/BuddyList.cs | 4 ++-- Dalamud/Game/ClientState/ClientState.cs | 5 ++--- .../ClientState/ClientStateAddressResolver.cs | 2 +- Dalamud/Game/ClientState/Conditions/Condition.cs | 4 +--- Dalamud/Game/ClientState/Fates/FateTable.cs | 4 ++-- Dalamud/Game/ClientState/GamePad/GamepadState.cs | 2 +- Dalamud/Game/ClientState/JobGauge/JobGauges.cs | 2 +- Dalamud/Game/ClientState/Keys/KeyState.cs | 2 +- Dalamud/Game/ClientState/Objects/ObjectTable.cs | 4 ++-- Dalamud/Game/ClientState/Objects/TargetManager.cs | 2 +- Dalamud/Game/ClientState/Party/PartyList.cs | 4 ++-- Dalamud/Game/Command/CommandManager.cs | 2 +- Dalamud/Game/Config/GameConfig.cs | 2 +- Dalamud/Game/Config/GameConfigAddressResolver.cs | 2 +- Dalamud/Game/DutyState/DutyState.cs | 2 +- .../Game/DutyState/DutyStateAddressResolver.cs | 2 +- Dalamud/Game/Framework.cs | 15 +++++++-------- Dalamud/Game/FrameworkAddressResolver.cs | 2 +- Dalamud/Game/GameLifecycle.cs | 2 +- Dalamud/Game/Gui/ChatGuiAddressResolver.cs | 4 +--- Dalamud/Game/Gui/Dtr/DtrBar.cs | 7 +++---- .../Game/Gui/FlyText/FlyTextGuiAddressResolver.cs | 4 +--- .../Gui/PartyFinder/PartyFinderAddressResolver.cs | 4 +--- .../Gui/PartyFinder/Types/JobFlagsExtensions.cs | 6 +++--- Dalamud/Game/Gui/Toast/ToastGuiAddressResolver.cs | 4 +--- .../Game/Internal/DXGI/SwapChainSigResolver.cs | 3 +-- .../Game/Internal/DXGI/SwapChainVtableResolver.cs | 3 +-- Dalamud/Game/Libc/LibcFunction.cs | 2 +- Dalamud/Game/Libc/LibcFunctionAddressResolver.cs | 2 +- .../Game/Network/GameNetworkAddressResolver.cs | 4 +--- Dalamud/Game/SigScanner.cs | 2 +- Dalamud/Game/Text/SeStringHandling/Payload.cs | 14 ++++++++------ Dalamud/Interface/Internal/TextureManager.cs | 2 +- .../Internal/Windows/TitleScreenMenuWindow.cs | 3 ++- Dalamud/Logging/Internal/TaskTracker.cs | 4 ++-- .../Internal/Profiles/ProfileCommandHandler.cs | 6 +++--- Dalamud/Plugin/Services/IFramework.cs | 7 +------ 40 files changed, 67 insertions(+), 86 deletions(-) diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index fb167283f..809726684 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -26,7 +26,7 @@ namespace Dalamud.Data; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed class DataManager : IDisposable, IServiceType, IDataManager +internal sealed class DataManager : IDisposable, IServiceType, IDataManager { private readonly Thread luminaResourceThread; private readonly CancellationTokenSource luminaCancellationTokenSource; diff --git a/Dalamud/Game/BaseAddressResolver.cs b/Dalamud/Game/BaseAddressResolver.cs index 24e7dffe8..9935aac7b 100644 --- a/Dalamud/Game/BaseAddressResolver.cs +++ b/Dalamud/Game/BaseAddressResolver.cs @@ -10,7 +10,7 @@ namespace Dalamud.Game; /// /// Base memory address resolver. /// -public abstract class BaseAddressResolver +internal abstract class BaseAddressResolver { /// /// Gets a list of memory addresses that were found, to list in /xldata. diff --git a/Dalamud/Game/ClientState/Aetherytes/AetheryteList.cs b/Dalamud/Game/ClientState/Aetherytes/AetheryteList.cs index 17b468d70..e6af6e1df 100644 --- a/Dalamud/Game/ClientState/Aetherytes/AetheryteList.cs +++ b/Dalamud/Game/ClientState/Aetherytes/AetheryteList.cs @@ -18,7 +18,7 @@ namespace Dalamud.Game.ClientState.Aetherytes; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed unsafe partial class AetheryteList : IServiceType, IAetheryteList +internal sealed unsafe partial class AetheryteList : IServiceType, IAetheryteList { [ServiceManager.ServiceDependency] private readonly ClientState clientState = Service.Get(); @@ -78,7 +78,7 @@ public sealed unsafe partial class AetheryteList : IServiceType, IAetheryteList /// /// This collection represents the list of available Aetherytes in the Teleport window. /// -public sealed partial class AetheryteList +internal sealed partial class AetheryteList { /// public int Count => this.Length; diff --git a/Dalamud/Game/ClientState/Buddy/BuddyList.cs b/Dalamud/Game/ClientState/Buddy/BuddyList.cs index dc2cb9fae..489e75bc3 100644 --- a/Dalamud/Game/ClientState/Buddy/BuddyList.cs +++ b/Dalamud/Game/ClientState/Buddy/BuddyList.cs @@ -20,7 +20,7 @@ namespace Dalamud.Game.ClientState.Buddy; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed partial class BuddyList : IServiceType, IBuddyList +internal sealed partial class BuddyList : IServiceType, IBuddyList { private const uint InvalidObjectID = 0xE0000000; @@ -147,7 +147,7 @@ public sealed partial class BuddyList : IServiceType, IBuddyList /// /// This collection represents the buddies present in your squadron or trust party. /// -public sealed partial class BuddyList +internal sealed partial class BuddyList { /// int IReadOnlyCollection.Count => this.Length; diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index 6817523af..cef802c81 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using Dalamud.Data; @@ -25,7 +24,7 @@ namespace Dalamud.Game.ClientState; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed class ClientState : IDisposable, IServiceType, IClientState +internal sealed class ClientState : IDisposable, IServiceType, IClientState { private readonly GameLifecycle lifecycle; private readonly ClientStateAddressResolver address; @@ -141,7 +140,7 @@ public sealed class ClientState : IDisposable, IServiceType, IClientState this.CfPop?.InvokeSafely(this, e); } - private void FrameworkOnOnUpdateEvent(Framework framework1) + private void FrameworkOnOnUpdateEvent(IFramework framework1) { var condition = Service.GetNullable(); var gameGui = Service.GetNullable(); diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index 369e620be..305dda454 100644 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs @@ -5,7 +5,7 @@ namespace Dalamud.Game.ClientState; /// /// Client state memory address resolver. /// -public sealed class ClientStateAddressResolver : BaseAddressResolver +internal sealed class ClientStateAddressResolver : BaseAddressResolver { // Static offsets diff --git a/Dalamud/Game/ClientState/Conditions/Condition.cs b/Dalamud/Game/ClientState/Conditions/Condition.cs index 585b762bf..0f8523e9b 100644 --- a/Dalamud/Game/ClientState/Conditions/Condition.cs +++ b/Dalamud/Game/ClientState/Conditions/Condition.cs @@ -1,5 +1,3 @@ -using System; - using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; @@ -92,7 +90,7 @@ internal sealed partial class Condition : IServiceType, ICondition framework.Update += this.FrameworkUpdate; } - private void FrameworkUpdate(Framework framework) + private void FrameworkUpdate(IFramework framework) { for (var i = 0; i < MaxConditionEntries; i++) { diff --git a/Dalamud/Game/ClientState/Fates/FateTable.cs b/Dalamud/Game/ClientState/Fates/FateTable.cs index 53196d5df..e9400842f 100644 --- a/Dalamud/Game/ClientState/Fates/FateTable.cs +++ b/Dalamud/Game/ClientState/Fates/FateTable.cs @@ -18,7 +18,7 @@ namespace Dalamud.Game.ClientState.Fates; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed partial class FateTable : IServiceType, IFateTable +internal sealed partial class FateTable : IServiceType, IFateTable { private readonly ClientStateAddressResolver address; @@ -110,7 +110,7 @@ public sealed partial class FateTable : IServiceType, IFateTable /// /// This collection represents the currently available Fate events. /// -public sealed partial class FateTable +internal sealed partial class FateTable { /// int IReadOnlyCollection.Count => this.Length; diff --git a/Dalamud/Game/ClientState/GamePad/GamepadState.cs b/Dalamud/Game/ClientState/GamePad/GamepadState.cs index bc5744047..8acb6ada5 100644 --- a/Dalamud/Game/ClientState/GamePad/GamepadState.cs +++ b/Dalamud/Game/ClientState/GamePad/GamepadState.cs @@ -21,7 +21,7 @@ namespace Dalamud.Game.ClientState.GamePad; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public unsafe class GamepadState : IDisposable, IServiceType, IGamepadState +internal unsafe class GamepadState : IDisposable, IServiceType, IGamepadState { private readonly Hook? gamepadPoll; diff --git a/Dalamud/Game/ClientState/JobGauge/JobGauges.cs b/Dalamud/Game/ClientState/JobGauge/JobGauges.cs index 683f5c61f..74e22ddbe 100644 --- a/Dalamud/Game/ClientState/JobGauge/JobGauges.cs +++ b/Dalamud/Game/ClientState/JobGauge/JobGauges.cs @@ -19,7 +19,7 @@ namespace Dalamud.Game.ClientState.JobGauge; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public class JobGauges : IServiceType, IJobGauges +internal class JobGauges : IServiceType, IJobGauges { private Dictionary cache = new(); diff --git a/Dalamud/Game/ClientState/Keys/KeyState.cs b/Dalamud/Game/ClientState/Keys/KeyState.cs index ba5cd06d9..03c5d59b9 100644 --- a/Dalamud/Game/ClientState/Keys/KeyState.cs +++ b/Dalamud/Game/ClientState/Keys/KeyState.cs @@ -28,7 +28,7 @@ namespace Dalamud.Game.ClientState.Keys; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public class KeyState : IServiceType, IKeyState +internal class KeyState : IServiceType, IKeyState { // 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 diff --git a/Dalamud/Game/ClientState/Objects/ObjectTable.cs b/Dalamud/Game/ClientState/Objects/ObjectTable.cs index 16cf7c277..c6320ccbb 100644 --- a/Dalamud/Game/ClientState/Objects/ObjectTable.cs +++ b/Dalamud/Game/ClientState/Objects/ObjectTable.cs @@ -21,7 +21,7 @@ namespace Dalamud.Game.ClientState.Objects; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed partial class ObjectTable : IServiceType, IObjectTable +internal sealed partial class ObjectTable : IServiceType, IObjectTable { private const int ObjectTableLength = 596; @@ -109,7 +109,7 @@ public sealed partial class ObjectTable : IServiceType, IObjectTable /// /// This collection represents the currently spawned FFXIV game objects. /// -public sealed partial class ObjectTable +internal sealed partial class ObjectTable { /// int IReadOnlyCollection.Count => this.Length; diff --git a/Dalamud/Game/ClientState/Objects/TargetManager.cs b/Dalamud/Game/ClientState/Objects/TargetManager.cs index 00bcaac7d..a821ba806 100644 --- a/Dalamud/Game/ClientState/Objects/TargetManager.cs +++ b/Dalamud/Game/ClientState/Objects/TargetManager.cs @@ -16,7 +16,7 @@ namespace Dalamud.Game.ClientState.Objects; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed unsafe class TargetManager : IServiceType, ITargetManager +internal sealed unsafe class TargetManager : IServiceType, ITargetManager { [ServiceManager.ServiceDependency] private readonly ClientState clientState = Service.Get(); diff --git a/Dalamud/Game/ClientState/Party/PartyList.cs b/Dalamud/Game/ClientState/Party/PartyList.cs index 529b57b6f..946c73245 100644 --- a/Dalamud/Game/ClientState/Party/PartyList.cs +++ b/Dalamud/Game/ClientState/Party/PartyList.cs @@ -19,7 +19,7 @@ namespace Dalamud.Game.ClientState.Party; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed unsafe partial class PartyList : IServiceType, IPartyList +internal sealed unsafe partial class PartyList : IServiceType, IPartyList { private const int GroupLength = 8; private const int AllianceLength = 20; @@ -130,7 +130,7 @@ public sealed unsafe partial class PartyList : IServiceType, IPartyList /// /// This collection represents the party members present in your party or alliance. /// -public sealed partial class PartyList +internal sealed partial class PartyList { /// int IReadOnlyCollection.Count => this.Length; diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs index 63a1a3d09..6a8651b41 100644 --- a/Dalamud/Game/Command/CommandManager.cs +++ b/Dalamud/Game/Command/CommandManager.cs @@ -23,7 +23,7 @@ namespace Dalamud.Game.Command; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed class CommandManager : IServiceType, IDisposable, ICommandManager +internal sealed class CommandManager : IServiceType, IDisposable, ICommandManager { private readonly ConcurrentDictionary commandMap = new(); private readonly Regex commandRegexEn = new(@"^The command (?.+) does not exist\.$", RegexOptions.Compiled); diff --git a/Dalamud/Game/Config/GameConfig.cs b/Dalamud/Game/Config/GameConfig.cs index 49d24c2a5..b77b9c4af 100644 --- a/Dalamud/Game/Config/GameConfig.cs +++ b/Dalamud/Game/Config/GameConfig.cs @@ -17,7 +17,7 @@ namespace Dalamud.Game.Config; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed class GameConfig : IServiceType, IGameConfig, IDisposable +internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable { private readonly GameConfigAddressResolver address = new(); private Hook? configChangeHook; diff --git a/Dalamud/Game/Config/GameConfigAddressResolver.cs b/Dalamud/Game/Config/GameConfigAddressResolver.cs index 6a207807a..674ee4764 100644 --- a/Dalamud/Game/Config/GameConfigAddressResolver.cs +++ b/Dalamud/Game/Config/GameConfigAddressResolver.cs @@ -3,7 +3,7 @@ /// /// Game config system address resolver. /// -public sealed class GameConfigAddressResolver : BaseAddressResolver +internal sealed class GameConfigAddressResolver : BaseAddressResolver { /// /// Gets the address of the method called when any config option is changed. diff --git a/Dalamud/Game/DutyState/DutyState.cs b/Dalamud/Game/DutyState/DutyState.cs index 2f117a492..34940dee0 100644 --- a/Dalamud/Game/DutyState/DutyState.cs +++ b/Dalamud/Game/DutyState/DutyState.cs @@ -135,7 +135,7 @@ internal unsafe class DutyState : IDisposable, IServiceType, IDutyState /// Joining a duty in progress, or disconnecting and reconnecting will cause the player to miss the event. /// /// Framework reference. - private void FrameworkOnUpdateEvent(Framework framework1) + private void FrameworkOnUpdateEvent(IFramework framework1) { // If the duty hasn't been started, and has not been completed yet this territory if (!this.IsDutyStarted && !this.CompletedThisTerritory) diff --git a/Dalamud/Game/DutyState/DutyStateAddressResolver.cs b/Dalamud/Game/DutyState/DutyStateAddressResolver.cs index 436883dc2..772af79a8 100644 --- a/Dalamud/Game/DutyState/DutyStateAddressResolver.cs +++ b/Dalamud/Game/DutyState/DutyStateAddressResolver.cs @@ -3,7 +3,7 @@ namespace Dalamud.Game.DutyState; /// /// Duty state memory address resolver. /// -public class DutyStateAddressResolver : BaseAddressResolver +internal class DutyStateAddressResolver : BaseAddressResolver { /// /// Gets the address of the method which is called when the client receives a content director update. diff --git a/Dalamud/Game/Framework.cs b/Dalamud/Game/Framework.cs index 2b77bf400..08b97edbc 100644 --- a/Dalamud/Game/Framework.cs +++ b/Dalamud/Game/Framework.cs @@ -27,7 +27,7 @@ namespace Dalamud.Game; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed class Framework : IDisposable, IServiceType, IFramework +internal sealed class Framework : IDisposable, IServiceType, IFramework { private static readonly Stopwatch StatsStopwatch = new(); @@ -39,6 +39,8 @@ public sealed class Framework : IDisposable, IServiceType, IFramework private readonly Hook updateHook; private readonly Hook destroyHook; + private readonly FrameworkAddressResolver addressResolver; + [ServiceManager.ServiceDependency] private readonly DalamudConfiguration configuration = Service.Get(); @@ -54,11 +56,11 @@ public sealed class Framework : IDisposable, IServiceType, IFramework this.lifecycle = lifecycle; this.hitchDetector = new HitchDetector("FrameworkUpdate", this.configuration.FrameworkUpdateHitch); - this.Address = new FrameworkAddressResolver(); - this.Address.Setup(sigScanner); + this.addressResolver = new FrameworkAddressResolver(); + this.addressResolver.Setup(sigScanner); - this.updateHook = Hook.FromAddress(this.Address.TickAddress, this.HandleFrameworkUpdate); - this.destroyHook = Hook.FromAddress(this.Address.DestroyAddress, this.HandleFrameworkDestroy); + this.updateHook = Hook.FromAddress(this.addressResolver.TickAddress, this.HandleFrameworkUpdate); + this.destroyHook = Hook.FromAddress(this.addressResolver.DestroyAddress, this.HandleFrameworkDestroy); } /// @@ -92,9 +94,6 @@ public sealed class Framework : IDisposable, IServiceType, IFramework /// public static Dictionary> StatsHistory { get; } = new(); - /// - public FrameworkAddressResolver Address { get; } - /// public DateTime LastUpdate { get; private set; } = DateTime.MinValue; diff --git a/Dalamud/Game/FrameworkAddressResolver.cs b/Dalamud/Game/FrameworkAddressResolver.cs index 36915d7a9..c47469a01 100644 --- a/Dalamud/Game/FrameworkAddressResolver.cs +++ b/Dalamud/Game/FrameworkAddressResolver.cs @@ -5,7 +5,7 @@ namespace Dalamud.Game; /// /// The address resolver for the class. /// -public sealed class FrameworkAddressResolver : BaseAddressResolver +internal sealed class FrameworkAddressResolver : BaseAddressResolver { /// /// Gets the address for the function that is called once the Framework is destroyed. diff --git a/Dalamud/Game/GameLifecycle.cs b/Dalamud/Game/GameLifecycle.cs index 5c1acc989..4192d055b 100644 --- a/Dalamud/Game/GameLifecycle.cs +++ b/Dalamud/Game/GameLifecycle.cs @@ -15,7 +15,7 @@ namespace Dalamud.Game; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public class GameLifecycle : IServiceType, IGameLifecycle +internal class GameLifecycle : IServiceType, IGameLifecycle { private readonly CancellationTokenSource dalamudUnloadCts = new(); private readonly CancellationTokenSource gameShutdownCts = new(); diff --git a/Dalamud/Game/Gui/ChatGuiAddressResolver.cs b/Dalamud/Game/Gui/ChatGuiAddressResolver.cs index 4686d5725..494e0b3ed 100644 --- a/Dalamud/Game/Gui/ChatGuiAddressResolver.cs +++ b/Dalamud/Game/Gui/ChatGuiAddressResolver.cs @@ -1,11 +1,9 @@ -using System; - namespace Dalamud.Game.Gui; /// /// The address resolver for the class. /// -public sealed class ChatGuiAddressResolver : BaseAddressResolver +internal sealed class ChatGuiAddressResolver : BaseAddressResolver { /// /// Gets the address of the native PrintMessage method. diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs index dd1e7aa30..c126825d5 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBar.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Dalamud.Configuration.Internal; @@ -22,7 +21,7 @@ namespace Dalamud.Game.Gui.Dtr; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar +internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar { private const uint BaseNodeId = 1000; @@ -133,7 +132,7 @@ public sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar private AtkUnitBase* GetDtr() => (AtkUnitBase*)this.gameGui.GetAddonByName("_DTR").ToPointer(); - private void Update(Framework unused) + private void Update(IFramework unused) { this.HandleRemovedNodes(); diff --git a/Dalamud/Game/Gui/FlyText/FlyTextGuiAddressResolver.cs b/Dalamud/Game/Gui/FlyText/FlyTextGuiAddressResolver.cs index 588177032..677d92e57 100644 --- a/Dalamud/Game/Gui/FlyText/FlyTextGuiAddressResolver.cs +++ b/Dalamud/Game/Gui/FlyText/FlyTextGuiAddressResolver.cs @@ -1,11 +1,9 @@ -using System; - namespace Dalamud.Game.Gui.FlyText; /// /// An address resolver for the class. /// -public class FlyTextGuiAddressResolver : BaseAddressResolver +internal class FlyTextGuiAddressResolver : BaseAddressResolver { /// /// Gets the address of the native AddFlyText method, which occurs diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderAddressResolver.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderAddressResolver.cs index aa9d28cb1..c12721358 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderAddressResolver.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderAddressResolver.cs @@ -1,11 +1,9 @@ -using System; - namespace Dalamud.Game.Gui.PartyFinder; /// /// The address resolver for the class. /// -public class PartyFinderAddressResolver : BaseAddressResolver +internal class PartyFinderAddressResolver : BaseAddressResolver { /// /// Gets the address of the native ReceiveListing method. diff --git a/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs b/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs index c7630acfa..46e83b972 100644 --- a/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs +++ b/Dalamud/Game/Gui/PartyFinder/Types/JobFlagsExtensions.cs @@ -1,4 +1,4 @@ -using Dalamud.Data; +using Dalamud.Plugin.Services; using Lumina.Excel.GeneratedSheets; namespace Dalamud.Game.Gui.PartyFinder.Types; @@ -14,7 +14,7 @@ public static class JobFlagsExtensions /// A JobFlags enum member. /// A DataManager to get the ClassJob from. /// A ClassJob if found or null if not. - public static ClassJob ClassJob(this JobFlags job, DataManager data) + public static ClassJob? ClassJob(this JobFlags job, IDataManager data) { var jobs = data.GetExcelSheet(); @@ -52,6 +52,6 @@ public static class JobFlagsExtensions _ => null, }; - return row == null ? null : jobs.GetRow((uint)row); + return row == null ? null : jobs?.GetRow((uint)row); } } diff --git a/Dalamud/Game/Gui/Toast/ToastGuiAddressResolver.cs b/Dalamud/Game/Gui/Toast/ToastGuiAddressResolver.cs index 4f935b465..ae5426023 100644 --- a/Dalamud/Game/Gui/Toast/ToastGuiAddressResolver.cs +++ b/Dalamud/Game/Gui/Toast/ToastGuiAddressResolver.cs @@ -1,11 +1,9 @@ -using System; - namespace Dalamud.Game.Gui.Toast; /// /// An address resolver for the class. /// -public class ToastGuiAddressResolver : BaseAddressResolver +internal class ToastGuiAddressResolver : BaseAddressResolver { /// /// Gets the address of the native ShowNormalToast method. diff --git a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs index ad79dff9f..a2fc08646 100644 --- a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs +++ b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Linq; @@ -10,7 +9,7 @@ namespace Dalamud.Game.Internal.DXGI; /// The address resolver for native D3D11 methods to facilitate displaying the Dalamud UI. /// [Obsolete("This has been deprecated in favor of the VTable resolver.")] -public sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver +internal sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver { /// public IntPtr Present { get; set; } diff --git a/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs index 603324175..50aae26ed 100644 --- a/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs +++ b/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; @@ -15,7 +14,7 @@ namespace Dalamud.Game.Internal.DXGI; /// /// If the normal signature based method of resolution fails, this is the backup. /// -public class SwapChainVtableResolver : BaseAddressResolver, ISwapChainAddressResolver +internal class SwapChainVtableResolver : BaseAddressResolver, ISwapChainAddressResolver { /// public IntPtr Present { get; set; } diff --git a/Dalamud/Game/Libc/LibcFunction.cs b/Dalamud/Game/Libc/LibcFunction.cs index 7dfc26b3b..b0bd4950c 100644 --- a/Dalamud/Game/Libc/LibcFunction.cs +++ b/Dalamud/Game/Libc/LibcFunction.cs @@ -17,7 +17,7 @@ namespace Dalamud.Game.Libc; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public sealed class LibcFunction : IServiceType, ILibcFunction +internal sealed class LibcFunction : IServiceType, ILibcFunction { private readonly LibcFunctionAddressResolver address; private readonly StdStringFromCStringDelegate stdStringCtorCString; diff --git a/Dalamud/Game/Libc/LibcFunctionAddressResolver.cs b/Dalamud/Game/Libc/LibcFunctionAddressResolver.cs index 89b721a87..4c3b7cdf8 100644 --- a/Dalamud/Game/Libc/LibcFunctionAddressResolver.cs +++ b/Dalamud/Game/Libc/LibcFunctionAddressResolver.cs @@ -5,7 +5,7 @@ namespace Dalamud.Game.Libc; /// /// The address resolver for the class. /// -public sealed class LibcFunctionAddressResolver : BaseAddressResolver +internal sealed class LibcFunctionAddressResolver : BaseAddressResolver { private delegate IntPtr StringFromCString(); diff --git a/Dalamud/Game/Network/GameNetworkAddressResolver.cs b/Dalamud/Game/Network/GameNetworkAddressResolver.cs index c698ee813..fa6af8c93 100644 --- a/Dalamud/Game/Network/GameNetworkAddressResolver.cs +++ b/Dalamud/Game/Network/GameNetworkAddressResolver.cs @@ -1,11 +1,9 @@ -using System; - namespace Dalamud.Game.Network; /// /// The address resolver for the class. /// -public sealed class GameNetworkAddressResolver : BaseAddressResolver +internal sealed class GameNetworkAddressResolver : BaseAddressResolver { /// /// Gets the address of the ProcessZonePacketDown method. diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs index b5fe0b5b3..ace4654be 100644 --- a/Dalamud/Game/SigScanner.cs +++ b/Dalamud/Game/SigScanner.cs @@ -25,7 +25,7 @@ namespace Dalamud.Game; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public class SigScanner : IDisposable, IServiceType, ISigScanner +internal class SigScanner : IDisposable, IServiceType, ISigScanner { private readonly FileInfo? cacheFile; diff --git a/Dalamud/Game/Text/SeStringHandling/Payload.cs b/Dalamud/Game/Text/SeStringHandling/Payload.cs index 117606a7a..ff7332f12 100644 --- a/Dalamud/Game/Text/SeStringHandling/Payload.cs +++ b/Dalamud/Game/Text/SeStringHandling/Payload.cs @@ -5,6 +5,7 @@ using System.IO; using Dalamud.Data; using Dalamud.Game.Text.SeStringHandling.Payloads; +using Dalamud.Plugin.Services; using Newtonsoft.Json; using Serilog; @@ -27,12 +28,6 @@ public abstract partial class Payload // To force-invalidate it, Dirty can be set to true private byte[] encodedData; - /// - /// Gets the Lumina instance to use for any necessary data lookups. - /// - [JsonIgnore] - public DataManager DataResolver => Service.Get(); - /// /// Gets the type of this payload. /// @@ -43,6 +38,13 @@ public abstract partial class Payload /// public bool Dirty { get; protected set; } = true; + /// + /// Gets the Lumina instance to use for any necessary data lookups. + /// + [JsonIgnore] + // TODO: We should refactor this. It should not be possible to get IDataManager through here. + protected IDataManager DataResolver => Service.Get(); + /// /// Decodes a binary representation of a payload into its corresponding nice object payload. /// diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index b397182ef..78af0ebb7 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -442,7 +442,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP } } - private void FrameworkOnUpdate(Framework fw) + private void FrameworkOnUpdate(IFramework fw) { lock (this.activeTextures) { diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index e3cf78296..20d260704 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -11,6 +11,7 @@ using Dalamud.Interface.Animation.EasingFunctions; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; +using Dalamud.Plugin.Services; using ImGuiNET; using ImGuiScene; @@ -358,7 +359,7 @@ internal class TitleScreenMenuWindow : Window, IDisposable return isHover; } - private void FrameworkOnUpdate(Framework framework) + private void FrameworkOnUpdate(IFramework framework) { var clientState = Service.Get(); this.IsOpen = !clientState.IsLoggedIn; diff --git a/Dalamud/Logging/Internal/TaskTracker.cs b/Dalamud/Logging/Internal/TaskTracker.cs index a8729893f..b65f0efa7 100644 --- a/Dalamud/Logging/Internal/TaskTracker.cs +++ b/Dalamud/Logging/Internal/TaskTracker.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; @@ -6,6 +5,7 @@ using System.Reflection; using System.Threading.Tasks; using Dalamud.Game; +using Dalamud.Plugin.Services; namespace Dalamud.Logging.Internal; @@ -141,7 +141,7 @@ internal class TaskTracker : IDisposable, IServiceType return true; } - private void FrameworkOnUpdate(Framework framework) + private void FrameworkOnUpdate(IFramework framework) { UpdateData(); } diff --git a/Dalamud/Plugin/Internal/Profiles/ProfileCommandHandler.cs b/Dalamud/Plugin/Internal/Profiles/ProfileCommandHandler.cs index 8ea55856c..7001e4d7b 100644 --- a/Dalamud/Plugin/Internal/Profiles/ProfileCommandHandler.cs +++ b/Dalamud/Plugin/Internal/Profiles/ProfileCommandHandler.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -7,6 +6,7 @@ using CheapLoc; using Dalamud.Game; using Dalamud.Game.Command; using Dalamud.Game.Gui; +using Dalamud.Plugin.Services; using Dalamud.Utility; using Serilog; @@ -78,7 +78,7 @@ internal class ProfileCommandHandler : IServiceType, IDisposable this.framework.Update += this.FrameworkOnUpdate; } - private void FrameworkOnUpdate(Framework framework1) + private void FrameworkOnUpdate(IFramework framework1) { if (this.profileManager.IsBusy) return; diff --git a/Dalamud/Plugin/Services/IFramework.cs b/Dalamud/Plugin/Services/IFramework.cs index 69c21bca4..334577b92 100644 --- a/Dalamud/Plugin/Services/IFramework.cs +++ b/Dalamud/Plugin/Services/IFramework.cs @@ -15,18 +15,13 @@ public interface IFramework /// A delegate type used with the event. /// /// The Framework instance. - public delegate void OnUpdateDelegate(Framework framework); + public delegate void OnUpdateDelegate(IFramework framework); /// /// Event that gets fired every time the game framework updates. /// public event OnUpdateDelegate Update; - /// - /// Gets a raw pointer to the instance of Client::Framework. - /// - public FrameworkAddressResolver Address { get; } - /// /// Gets the last time that the Framework Update event was triggered. /// From 00fa1dc4f83beea0373aa15ddcaef16a9bf88547 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 17 Sep 2023 23:02:42 +0200 Subject: [PATCH 062/120] chore: remove ChatHandlers public service --- Dalamud/Game/ChatHandlers.cs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index 1d82e5f9c..896d296fc 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -25,10 +25,8 @@ namespace Dalamud.Game; /// /// Chat events and public helper functions. /// -[PluginInterface] -[InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -public class ChatHandlers : IServiceType +internal class ChatHandlers : IServiceType { // private static readonly Dictionary UnicodeToDiscordEmojiDict = new() // { @@ -134,22 +132,6 @@ public class ChatHandlers : IServiceType /// public bool IsAutoUpdateComplete { get; private set; } - /// - /// Convert a TextPayload to SeString and wrap in italics payloads. - /// - /// Text to convert. - /// SeString payload of italicized text. - public static SeString MakeItalics(string text) - => MakeItalics(new TextPayload(text)); - - /// - /// Convert a TextPayload to SeString and wrap in italics payloads. - /// - /// Text to convert. - /// SeString payload of italicized text. - public static SeString MakeItalics(TextPayload text) - => new(EmphasisItalicPayload.ItalicsOn, text, EmphasisItalicPayload.ItalicsOff); - private void OnCheckMessageHandled(XivChatType type, uint senderid, ref SeString sender, ref SeString message, ref bool isHandled) { var textVal = message.TextValue; From 3d94d07f56b0d959b10ad1f5ab9c025e1ade8c69 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 17 Sep 2023 23:13:16 +0200 Subject: [PATCH 063/120] chore: remove opcodes from public API --- Dalamud/Plugin/Services/IDataManager.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Dalamud/Plugin/Services/IDataManager.cs b/Dalamud/Plugin/Services/IDataManager.cs index 3ae10b0c7..4977b65b3 100644 --- a/Dalamud/Plugin/Services/IDataManager.cs +++ b/Dalamud/Plugin/Services/IDataManager.cs @@ -19,17 +19,7 @@ public interface IDataManager /// Gets the current game client language. /// public ClientLanguage Language { get; } - - /// - /// Gets the OpCodes sent by the server to the client. - /// - public ReadOnlyDictionary ServerOpCodes { get; } - - /// - /// Gets the OpCodes sent by the client to the server. - /// - public ReadOnlyDictionary ClientOpCodes { get; } - + /// /// Gets a object which gives access to any excel/game data. /// From 9d4a2fad3bd1fff50cd1bfd6d7f44fdb13df0695 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 17 Sep 2023 23:39:09 +0200 Subject: [PATCH 064/120] fix dtr errors after merge --- Dalamud/Game/Gui/Dtr/DtrBar.cs | 3 ++- Dalamud/Game/Gui/Dtr/DtrBarAddressResolver.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs index 4e9584f27..42f06443f 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBar.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using Dalamud.Configuration.Internal; diff --git a/Dalamud/Game/Gui/Dtr/DtrBarAddressResolver.cs b/Dalamud/Game/Gui/Dtr/DtrBarAddressResolver.cs index 1e6fd09cd..744d926f0 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBarAddressResolver.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBarAddressResolver.cs @@ -3,7 +3,7 @@ /// /// DtrBar memory address resolver. /// -public class DtrBarAddressResolver : BaseAddressResolver +internal class DtrBarAddressResolver : BaseAddressResolver { /// /// Gets the address of the AtkUnitBaseDraw method. From 4989e2b69b8ce23dbe01b8a6786267e6a0ed6ea2 Mon Sep 17 00:00:00 2001 From: Aireil <33433913+Aireil@users.noreply.github.com> Date: Mon, 18 Sep 2023 03:55:43 +0200 Subject: [PATCH 065/120] refactor: rename fly text kind members --- Dalamud/Game/Gui/FlyText/FlyTextKind.cs | 144 +++++++++++++----------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/Dalamud/Game/Gui/FlyText/FlyTextKind.cs b/Dalamud/Game/Gui/FlyText/FlyTextKind.cs index 68650fb5c..3727fd0f8 100644 --- a/Dalamud/Game/Gui/FlyText/FlyTextKind.cs +++ b/Dalamud/Game/Gui/FlyText/FlyTextKind.cs @@ -1,57 +1,58 @@ namespace Dalamud.Game.Gui.FlyText; /// -/// Enum of FlyTextKind values. Members suffixed with -/// a number seem to be a duplicate, or perform duplicate behavior. +/// Enum of FlyTextKind values. /// public enum FlyTextKind : int { /// /// Val1 in serif font, Text2 in sans-serif as subtitle. - /// Used for autos and incoming DoTs. /// - AutoAttack = 0, + AutoAttackOrDot = 0, /// /// Val1 in serif font, Text2 in sans-serif as subtitle. /// Does a bounce effect on appearance. /// - DirectHit = 1, + AutoAttackOrDotDh = 1, /// /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle. /// Does a bigger bounce effect on appearance. /// - CriticalHit = 2, + AutoAttackOrDotCrit = 2, /// - /// Val1 in even larger serif font with 2 exclamations, Text2 in - /// sans-serif as subtitle. Does a large bounce effect on appearance. - /// Does not scroll up or down the screen. + /// Val1 in even larger serif font with 2 exclamations, Text2 in sans-serif as subtitle. + /// Does a large bounce effect on appearance. Does not scroll up or down the screen. /// - CriticalDirectHit = 3, + AutoAttackOrDotCritDh = 3, /// - /// AutoAttack with sans-serif Text1 to the left of the Val1. + /// Val1 in serif font, Text2 in sans-serif as subtitle with sans-serif Text1 to the left of the Val1. /// - NamedAttack = 4, + Damage = 4, /// - /// DirectHit with sans-serif Text1 to the left of the Val1. + /// Val1 in serif font, Text2 in sans-serif as subtitle with sans-serif Text1 to the left of the Val1. + /// Does a bounce effect on appearance. /// - NamedDirectHit = 5, + DamageDh = 5, /// - /// CriticalHit with sans-serif Text1 to the left of the Val1. + /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle with sans-serif Text1 to the left of the Val1. + /// Does a bigger bounce effect on appearance. /// - NamedCriticalHit = 6, + DamageCrit = 6, /// - /// CriticalDirectHit with sans-serif Text1 to the left of the Val1. + /// Val1 in even larger serif font with 2 exclamations, Text2 in sans-serif as subtitle with sans-serif Text1 to the left of the Val1. + /// Does a large bounce effect on appearance. Does not scroll up or down the screen. /// - NamedCriticalDirectHit = 7, + DamageCritDh = 7, /// + /// The text changes to DODGE under certain circumstances. /// All caps, serif MISS. /// Miss = 8, @@ -74,12 +75,12 @@ public enum FlyTextKind : int /// /// Icon next to sans-serif Text1. /// - NamedIcon = 12, + Buff = 12, /// - /// Icon next to sans-serif Text1 (2). + /// Icon next to sans-serif Text1. /// - NamedIcon2 = 13, + Debuff = 13, /// /// Serif Val1 with all caps condensed font EXP with Text2 in sans-serif as subtitle. @@ -94,42 +95,44 @@ public enum FlyTextKind : int /// /// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle. /// - NamedMp = 16, + MpDrain = 16, /// + /// Currently not used by the game. /// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle. /// NamedTp = 17, /// - /// AutoAttack with sans-serif Text1 to the left of the Val1 (2). + /// Val1 in serif font, Text2 in sans-serif as subtitle with sans-serif Text1 to the left of the Val1. /// - NamedAttack2 = 18, + Healing = 18, /// - /// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle (2). + /// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle. /// - NamedMp2 = 19, + MpRegen = 19, /// - /// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle (2). + /// Currently not used by the game. + /// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle. /// NamedTp2 = 20, /// /// Sans-serif Text1 next to serif Val1 with all caps condensed font EP with Text2 in sans-serif as subtitle. /// - NamedEp = 21, + EpRegen = 21, /// /// Sans-serif Text1 next to serif Val1 with all caps condensed font CP with Text2 in sans-serif as subtitle. /// - NamedCp = 22, + CpRegen = 22, /// /// Sans-serif Text1 next to serif Val1 with all caps condensed font GP with Text2 in sans-serif as subtitle. /// - NamedGp = 23, + GpRegen = 23, /// /// Displays nothing. @@ -149,57 +152,59 @@ public enum FlyTextKind : int Interrupted = 26, /// - /// AutoAttack with no Text2. + /// Val1 in serif font. /// - AutoAttackNoText = 27, + CraftingProgress = 27, /// - /// AutoAttack with no Text2 (2). + /// Val1 in serif font. /// - AutoAttackNoText2 = 28, + CraftingQuality = 28, /// - /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle. Does a bigger bounce effect on appearance (2). + /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle. Does a bigger bounce effect on appearance. /// - CriticalHit2 = 29, + CraftingQualityCrit = 29, /// - /// AutoAttack with no Text2 (3). + /// Currently not used by the game. + /// Val1 in serif font. /// AutoAttackNoText3 = 30, /// /// CriticalHit with sans-serif Text1 to the left of the Val1 (2). /// - NamedCriticalHit2 = 31, + HealingCrit = 31, /// - /// Same as NamedCriticalHit with a green (cannot change) MP in condensed font to the right of Val1. + /// Currently not used by the game. + /// Same as DamageCrit with a MP in condensed font to the right of Val1. /// Does a jiggle effect to the right on appearance. /// NamedCriticalHitWithMp = 32, /// - /// Same as NamedCriticalHit with a yellow (cannot change) TP in condensed font to the right of Val1. + /// Currently not used by the game. + /// Same as DamageCrit with a TP in condensed font to the right of Val1. /// Does a jiggle effect to the right on appearance. /// NamedCriticalHitWithTp = 33, /// - /// Same as NamedIcon with sans-serif "has no effect!" to the right. + /// Icon next to sans-serif Text1 with sans-serif "has no effect!" to the right. /// - NamedIconHasNoEffect = 34, + DebuffNoEffect = 34, /// - /// Same as NamedIcon but Text1 is slightly faded. Used for buff expiration. + /// Icon next to sans-serif slightly faded Text1. /// - NamedIconFaded = 35, + BuffFading = 35, /// - /// Same as NamedIcon but Text1 is slightly faded (2). - /// Used for buff expiration. + /// Icon next to sans-serif slightly faded Text1. /// - NamedIconFaded2 = 36, + DebuffFading = 36, /// /// Text1 in sans-serif font. @@ -207,9 +212,9 @@ public enum FlyTextKind : int Named = 37, /// - /// Same as NamedIcon with sans-serif "(fully resisted)" to the right. + /// Icon next to sans-serif Text1 with sans-serif "(fully resisted)" to the right. /// - NamedIconFullyResisted = 38, + DebuffResisted = 38, /// /// All caps serif 'INCAPACITATED!'. @@ -219,32 +224,34 @@ public enum FlyTextKind : int /// /// Text1 with sans-serif "(fully resisted)" to the right. /// - NamedFullyResisted = 40, + FullyResisted = 40, /// /// Text1 with sans-serif "has no effect!" to the right. /// - NamedHasNoEffect = 41, + HasNoEffect = 41, /// - /// AutoAttack with sans-serif Text1 to the left of the Val1 (3). + /// Val1 in serif font, Text2 in sans-serif as subtitle with sans-serif Text1 to the left of the Val1. /// - NamedAttack3 = 42, + HpDrain = 42, /// - /// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle (3). + /// Currently not used by the game. + /// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle. /// NamedMp3 = 43, /// - /// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle (3). + /// Currently not used by the game. + /// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle. /// NamedTp3 = 44, /// - /// Same as NamedIcon with serif "INVULNERABLE!" beneath the Text1. + /// Icon next to sans-serif Text1 with serif "INVULNERABLE!" beneath the Text1. /// - NamedIconInvulnerable = 45, + DebuffInvulnerable = 45, /// /// All caps serif RESIST. @@ -252,20 +259,20 @@ public enum FlyTextKind : int Resist = 46, /// - /// Same as NamedIcon but places the given icon in the item icon outline. + /// Icon with an item icon outline next to sans-serif Text1. /// - NamedIconWithItemOutline = 47, + LootedItem = 47, /// - /// AutoAttack with no Text2 (4). + /// Val1 in serif font. /// - AutoAttackNoText4 = 48, + Collectability = 48, /// - /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle (3). + /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle. /// Does a bigger bounce effect on appearance. /// - CriticalHit3 = 49, + CollectabilityCrit = 49, /// /// All caps serif REFLECT. @@ -278,20 +285,21 @@ public enum FlyTextKind : int Reflected = 51, /// - /// Val1 in serif font, Text2 in sans-serif as subtitle (2). + /// Val1 in serif font, Text2 in sans-serif as subtitle. /// Does a bounce effect on appearance. /// - DirectHit2 = 52, + CraftingQualityDh = 52, /// - /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle (4). + /// Currently not used by the game. + /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle. /// Does a bigger bounce effect on appearance. /// CriticalHit4 = 53, /// - /// Val1 in even larger serif font with 2 exclamations, Text2 in sans-serif as subtitle (2). + /// Val1 in even larger serif font with 2 exclamations, Text2 in sans-serif as subtitle. /// Does a large bounce effect on appearance. Does not scroll up or down the screen. /// - CriticalDirectHit2 = 54, + CraftingQualityCritDh = 54, } From af39add38e3f93761f0774fd488245613af0c331 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Mon, 18 Sep 2023 09:18:01 +0200 Subject: [PATCH 066/120] [v9] Update ClientStructs and fix build (#1398) * Update ClientStructs * Use IFramework in AddonLifecycle * Fix for ClientStructs breaking changes --- Dalamud/Game/AddonLifecycle/AddonLifecycle.cs | 4 ++-- Dalamud/Interface/Internal/UiDebug.cs | 10 +++++----- lib/FFXIVClientStructs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Dalamud/Game/AddonLifecycle/AddonLifecycle.cs b/Dalamud/Game/AddonLifecycle/AddonLifecycle.cs index 5fc1c7d2b..5a1070dfb 100644 --- a/Dalamud/Game/AddonLifecycle/AddonLifecycle.cs +++ b/Dalamud/Game/AddonLifecycle/AddonLifecycle.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -97,7 +97,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType } // Used to prevent concurrency issues if plugins try to register during iteration of listeners. - private void OnFrameworkUpdate(Framework unused) + private void OnFrameworkUpdate(IFramework unused) { if (this.newEventListeners.Any()) { diff --git a/Dalamud/Interface/Internal/UiDebug.cs b/Dalamud/Interface/Internal/UiDebug.cs index b1f27828c..524759f4a 100644 --- a/Dalamud/Interface/Internal/UiDebug.cs +++ b/Dalamud/Interface/Internal/UiDebug.cs @@ -1,5 +1,6 @@ using System; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Dalamud.Game; @@ -416,7 +417,7 @@ internal unsafe class UiDebug $"MultiplyRGB: {node->MultiplyRed} {node->MultiplyGreen} {node->MultiplyBlue}"); } - private bool DrawUnitListHeader(int index, uint count, ulong ptr, bool highlight) + private bool DrawUnitListHeader(int index, ushort count, ulong ptr, bool highlight) { ImGui.PushStyleColor(ImGuiCol.Text, highlight ? 0xFFAAAA00 : 0xFFFFFFFF); if (!string.IsNullOrEmpty(this.searchInput) && !this.doingSearch) @@ -455,8 +456,6 @@ internal unsafe class UiDebug this.selectedInList[i] = false; var unitManager = &unitManagers[i]; - var unitBaseArray = &unitManager->AtkUnitEntries; - var headerOpen = true; if (!searching) @@ -468,7 +467,7 @@ internal unsafe class UiDebug for (var j = 0; j < unitManager->Count && headerOpen; j++) { - var unitBase = unitBaseArray[j]; + var unitBase = *(AtkUnitBase**)Unsafe.AsPointer(ref unitManager->EntriesSpan[j]); if (this.selectedUnitBase != null && unitBase == this.selectedUnitBase) { this.selectedInList[i] = true; @@ -513,7 +512,8 @@ internal unsafe class UiDebug { for (var j = 0; j < unitManager->Count; j++) { - if (this.selectedUnitBase == null || unitBaseArray[j] != this.selectedUnitBase) continue; + var unitBase = *(AtkUnitBase**)Unsafe.AsPointer(ref unitManager->EntriesSpan[j]); + if (this.selectedUnitBase == null || unitBase != this.selectedUnitBase) continue; this.selectedInList[i] = true; foundSelected = true; } diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index 06e3ca233..fd5ba8a27 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit 06e3ca2336031ba86ef95d022a2af722e5d00a7e +Subproject commit fd5ba8a27ec911a69eeb93ceb0202091279dfceb From 7a0f58a1063adef5223ca5e8a364cffdfd45d19e Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 18 Sep 2023 00:19:31 -0700 Subject: [PATCH 067/120] Remove PluginInterface from base Dtr service (#1399) --- Dalamud/Game/Gui/Dtr/DtrBar.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs index 42f06443f..5467e207f 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBar.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs @@ -22,12 +22,8 @@ namespace Dalamud.Game.Gui.Dtr; /// /// Class used to interface with the server info bar. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar { private const uint BaseNodeId = 1000; From 3e8be33a5cfb916bf28633521fe228b6e570a609 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 18 Sep 2023 10:45:42 -0700 Subject: [PATCH 068/120] Add CommandManagerPluginScoped --- Dalamud/Game/Command/CommandManager.cs | 76 ++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs index 6a8651b41..56630a5ad 100644 --- a/Dalamud/Game/Command/CommandManager.cs +++ b/Dalamud/Game/Command/CommandManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -17,12 +16,8 @@ namespace Dalamud.Game.Command; /// /// This class manages registered in-game slash commands. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 internal sealed class CommandManager : IServiceType, IDisposable, ICommandManager { private readonly ConcurrentDictionary commandMap = new(); @@ -84,7 +79,7 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage // => command: 0-12 (12 chars) // => argument: 13-17 (4 chars) // => content.IndexOf(' ') == 12 - command = content.Substring(0, separatorPosition); + command = content[..separatorPosition]; var argStart = separatorPosition + 1; argument = content[argStart..]; @@ -162,3 +157,72 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage } } } + +/// +/// Plugin-scoped version of a AddonLifecycle service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandManager +{ + [ServiceManager.ServiceDependency] + private readonly CommandManager commandManagerService = Service.Get(); + + private readonly List pluginRegisteredCommands = new(); + + /// + public ReadOnlyDictionary Commands => this.commandManagerService.Commands; + + /// + public void Dispose() + { + foreach (var command in this.pluginRegisteredCommands) + { + this.commandManagerService.RemoveHandler(command); + } + + this.pluginRegisteredCommands.Clear(); + } + + /// + public bool ProcessCommand(string content) + => this.commandManagerService.ProcessCommand(content); + + /// + public void DispatchCommand(string command, string argument, CommandInfo info) + => this.commandManagerService.DispatchCommand(command, argument, info); + + /// + public bool AddHandler(string command, CommandInfo info) + { + if (!this.pluginRegisteredCommands.Contains(command)) + { + if (this.commandManagerService.AddHandler(command, info)) + { + this.pluginRegisteredCommands.Add(command); + return true; + } + } + + return false; + } + + /// + public bool RemoveHandler(string command) + { + if (this.pluginRegisteredCommands.Contains(command)) + { + if (this.commandManagerService.RemoveHandler(command)) + { + this.pluginRegisteredCommands.Remove(command); + return true; + } + } + + return false; + } +} From 34617cf377b7805b0fa60296fcfccb3af73c6ca1 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 18 Sep 2023 10:50:05 -0700 Subject: [PATCH 069/120] Add error logging --- Dalamud/Game/Command/CommandManager.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs index 56630a5ad..118d210e2 100644 --- a/Dalamud/Game/Command/CommandManager.cs +++ b/Dalamud/Game/Command/CommandManager.cs @@ -8,8 +8,8 @@ using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; -using Serilog; namespace Dalamud.Game.Command; @@ -20,6 +20,8 @@ namespace Dalamud.Game.Command; [ServiceManager.BlockingEarlyLoadedService] internal sealed class CommandManager : IServiceType, IDisposable, ICommandManager { + private static readonly ModuleLog Log = new("Command"); + private readonly ConcurrentDictionary commandMap = new(); private readonly Regex commandRegexEn = new(@"^The command (?.+) does not exist\.$", RegexOptions.Compiled); private readonly Regex commandRegexJp = new(@"^そのコマンドはありません。: (?.+)$", RegexOptions.Compiled); @@ -169,6 +171,8 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage #pragma warning restore SA1015 internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandManager { + private static readonly ModuleLog Log = new("Command"); + [ServiceManager.ServiceDependency] private readonly CommandManager commandManagerService = Service.Get(); @@ -207,6 +211,10 @@ internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandM return true; } } + else + { + Log.Error($"Command {command} is already registered."); + } return false; } @@ -222,6 +230,10 @@ internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandM return true; } } + else + { + Log.Error($"Command {command} not found."); + } return false; } From 5d0694918572281ba0ac2a00915691406bf5f2ef Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:00:49 -0700 Subject: [PATCH 070/120] Set CommandInfo InternalName when adding to CommandManager via PluginScopedService --- Dalamud/Game/Command/CommandInfo.cs | 1 - Dalamud/Game/Command/CommandManager.cs | 12 ++++++++++++ .../Windows/PluginInstaller/PluginInstallerWindow.cs | 4 +--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Dalamud/Game/Command/CommandInfo.cs b/Dalamud/Game/Command/CommandInfo.cs index 9b559599a..bc0250a66 100644 --- a/Dalamud/Game/Command/CommandInfo.cs +++ b/Dalamud/Game/Command/CommandInfo.cs @@ -15,7 +15,6 @@ public sealed class CommandInfo public CommandInfo(HandlerDelegate handler) { this.Handler = handler; - this.LoaderAssemblyName = Assembly.GetCallingAssembly()?.GetName()?.Name; } /// diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs index 118d210e2..218b89676 100644 --- a/Dalamud/Game/Command/CommandManager.cs +++ b/Dalamud/Game/Command/CommandManager.cs @@ -9,6 +9,7 @@ using Dalamud.Game.Text.SeStringHandling; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Logging.Internal; +using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Services; namespace Dalamud.Game.Command; @@ -177,7 +178,17 @@ internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandM private readonly CommandManager commandManagerService = Service.Get(); private readonly List pluginRegisteredCommands = new(); + private readonly LocalPlugin pluginInfo; + /// + /// Initializes a new instance of the class. + /// + /// Info for the plugin that requests this service. + public CommandManagerPluginScoped(LocalPlugin localPlugin) + { + this.pluginInfo = localPlugin; + } + /// public ReadOnlyDictionary Commands => this.commandManagerService.Commands; @@ -205,6 +216,7 @@ internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandM { if (!this.pluginRegisteredCommands.Contains(command)) { + info.LoaderAssemblyName = this.pluginInfo.InternalName; if (this.commandManagerService.AddHandler(command, info)) { this.pluginRegisteredCommands.Add(command); diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index e5d3c147b..dcbdced28 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -15,7 +15,6 @@ using Dalamud.Game.Command; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Internal.Notifications; -using Dalamud.Interface.Style; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; @@ -2227,8 +2226,7 @@ internal class PluginInstallerWindow : Window, IDisposable { var commands = commandManager.Commands .Where(cInfo => - cInfo.Value != null && - cInfo.Value.ShowInHelp && + cInfo.Value is { ShowInHelp: true } && cInfo.Value.LoaderAssemblyName == plugin.Manifest.InternalName) .ToArray(); From dde1dd2f552fdfc85ac3940643706749645700d9 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:16:45 -0700 Subject: [PATCH 071/120] Add Clear button to NetworkMonitorWidget --- .../Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs index 8212c2e95..e7bce0b84 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/NetworkMonitorWidget.cs @@ -98,6 +98,11 @@ internal class NetworkMonitorWidget : IDataWindowWidget this.trackedPackets = Math.Clamp(this.trackedPackets, 1, 512); } + if (ImGui.Button("Clear Stored Packets")) + { + this.packets.Clear(); + } + this.DrawFilterInput(); this.DrawNegativeFilterInput(); From a61e181bde092988c5fac6c984b2dead307179db Mon Sep 17 00:00:00 2001 From: goat Date: Tue, 19 Sep 2023 19:28:26 +0200 Subject: [PATCH 072/120] fix warning in DataManager --- Dalamud/Data/DataManager.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index 809726684..f1f98229a 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -126,10 +126,14 @@ internal sealed class DataManager : IDisposable, IServiceType, IDataManager /// public ClientLanguage Language { get; private set; } - /// + /// + /// Gets a list of server opcodes. + /// public ReadOnlyDictionary ServerOpCodes { get; private set; } - - /// + + /// + /// Gets a list of client opcodes. + /// [UsedImplicitly] public ReadOnlyDictionary ClientOpCodes { get; private set; } From c305c01dfdc8482a6c5abf4fdf5b290f55d57529 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Tue, 19 Sep 2023 23:43:45 -0700 Subject: [PATCH 073/120] Nullify Scoped Service Delegates --- Dalamud/Game/ClientState/Conditions/Condition.cs | 2 ++ Dalamud/Game/DutyState/DutyState.cs | 5 +++++ Dalamud/Game/Gui/ChatGui.cs | 5 +++++ Dalamud/Game/Gui/FlyText/FlyTextGui.cs | 2 ++ Dalamud/Game/Gui/GameGui.cs | 4 ++++ Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs | 2 ++ Dalamud/Game/Gui/Toast/ToastGui.cs | 4 ++++ Dalamud/Game/Network/GameNetwork.cs | 2 ++ Dalamud/Utility/Util.cs | 2 +- 9 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Dalamud/Game/ClientState/Conditions/Condition.cs b/Dalamud/Game/ClientState/Conditions/Condition.cs index 0f8523e9b..2db47ea4d 100644 --- a/Dalamud/Game/ClientState/Conditions/Condition.cs +++ b/Dalamud/Game/ClientState/Conditions/Condition.cs @@ -189,6 +189,8 @@ internal class ConditionPluginScoped : IDisposable, IServiceType, ICondition public void Dispose() { this.conditionService.ConditionChange -= this.ConditionChangedForward; + + this.ConditionChange = null; } /// diff --git a/Dalamud/Game/DutyState/DutyState.cs b/Dalamud/Game/DutyState/DutyState.cs index 34940dee0..c52ceff0f 100644 --- a/Dalamud/Game/DutyState/DutyState.cs +++ b/Dalamud/Game/DutyState/DutyState.cs @@ -210,6 +210,11 @@ internal class DutyStatePluginScoped : IDisposable, IServiceType, IDutyState this.dutyStateService.DutyWiped -= this.DutyWipedForward; this.dutyStateService.DutyRecommenced -= this.DutyRecommencedForward; this.dutyStateService.DutyCompleted -= this.DutyCompletedForward; + + this.DutyStarted = null; + this.DutyWiped = null; + this.DutyRecommenced = null; + this.DutyCompleted = null; } private void DutyStartedForward(object sender, ushort territoryId) => this.DutyStarted?.Invoke(sender, territoryId); diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs index 2fbeb404e..55c919ab5 100644 --- a/Dalamud/Game/Gui/ChatGui.cs +++ b/Dalamud/Game/Gui/ChatGui.cs @@ -460,6 +460,11 @@ internal class ChatGuiPluginScoped : IDisposable, IServiceType, IChatGui this.chatGuiService.CheckMessageHandled -= this.OnCheckMessageForward; this.chatGuiService.ChatMessageHandled -= this.OnMessageHandledForward; this.chatGuiService.ChatMessageUnhandled -= this.OnMessageUnhandledForward; + + this.ChatMessage = null; + this.CheckMessageHandled = null; + this.ChatMessageHandled = null; + this.ChatMessageUnhandled = null; } /// diff --git a/Dalamud/Game/Gui/FlyText/FlyTextGui.cs b/Dalamud/Game/Gui/FlyText/FlyTextGui.cs index 3c04c744a..64de4b2dd 100644 --- a/Dalamud/Game/Gui/FlyText/FlyTextGui.cs +++ b/Dalamud/Game/Gui/FlyText/FlyTextGui.cs @@ -307,6 +307,8 @@ internal class FlyTextGuiPluginScoped : IDisposable, IServiceType, IFlyTextGui public void Dispose() { this.flyTextGuiService.FlyTextCreated -= this.FlyTextCreatedForward; + + this.FlyTextCreated = null; } /// diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 078c624e8..349d2a424 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -566,6 +566,10 @@ internal class GameGuiPluginScoped : IDisposable, IServiceType, IGameGui this.gameGuiService.UiHideToggled -= this.UiHideToggledForward; this.gameGuiService.HoveredItemChanged -= this.HoveredItemForward; this.gameGuiService.HoveredActionChanged -= this.HoveredActionForward; + + this.UiHideToggled = null; + this.HoveredItemChanged = null; + this.HoveredActionChanged = null; } /// diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs index 41a8ba56a..4bd93cdf0 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs @@ -156,6 +156,8 @@ internal class PartyFinderGuiPluginScoped : IDisposable, IServiceType, IPartyFin public void Dispose() { this.partyFinderGuiService.ReceiveListing -= this.ReceiveListingForward; + + this.ReceiveListing = null; } private void ReceiveListingForward(PartyFinderListing listing, PartyFinderListingEventArgs args) => this.ReceiveListing?.Invoke(listing, args); diff --git a/Dalamud/Game/Gui/Toast/ToastGui.cs b/Dalamud/Game/Gui/Toast/ToastGui.cs index 93126710b..9624e3e72 100644 --- a/Dalamud/Game/Gui/Toast/ToastGui.cs +++ b/Dalamud/Game/Gui/Toast/ToastGui.cs @@ -417,6 +417,10 @@ internal class ToastGuiPluginScoped : IDisposable, IServiceType, IToastGui this.toastGuiService.Toast -= this.ToastForward; this.toastGuiService.QuestToast -= this.QuestToastForward; this.toastGuiService.ErrorToast -= this.ErrorToastForward; + + this.Toast = null; + this.QuestToast = null; + this.ErrorToast = null; } /// diff --git a/Dalamud/Game/Network/GameNetwork.cs b/Dalamud/Game/Network/GameNetwork.cs index f56fd3996..7c900ece4 100644 --- a/Dalamud/Game/Network/GameNetwork.cs +++ b/Dalamud/Game/Network/GameNetwork.cs @@ -169,6 +169,8 @@ internal class GameNetworkPluginScoped : IDisposable, IServiceType, IGameNetwork public void Dispose() { this.gameNetworkService.NetworkMessage -= this.NetworkMessageForward; + + this.NetworkMessage = null; } private void NetworkMessageForward(nint dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 78edda3dd..c386ee23e 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -651,7 +651,7 @@ public static class Util /// /// The path of the file to write to. /// The text to write. - internal static void WriteAllTextSafe(string path, string text) + public static void WriteAllTextSafe(string path, string text) { var tmpPath = path + ".tmp"; if (File.Exists(tmpPath)) From 2b2a027fb08aca6e7400b2cf5afbb886a8f9ac76 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Tue, 19 Sep 2023 23:44:56 -0700 Subject: [PATCH 074/120] Move WriteAllTextSafe to correct location --- Dalamud/Utility/Util.cs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index c386ee23e..8ca87b691 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -609,7 +609,23 @@ public static class Util } } } + + /// + /// Overwrite text in a file by first writing it to a temporary file, and then + /// moving that file to the path specified. + /// + /// The path of the file to write to. + /// The text to write. + public static void WriteAllTextSafe(string path, string text) + { + var tmpPath = path + ".tmp"; + if (File.Exists(tmpPath)) + File.Delete(tmpPath); + File.WriteAllText(tmpPath, text); + File.Move(tmpPath, path, true); + } + /// /// Dispose this object. /// @@ -645,22 +661,6 @@ public static class Util } } - /// - /// Overwrite text in a file by first writing it to a temporary file, and then - /// moving that file to the path specified. - /// - /// The path of the file to write to. - /// The text to write. - public static void WriteAllTextSafe(string path, string text) - { - var tmpPath = path + ".tmp"; - if (File.Exists(tmpPath)) - File.Delete(tmpPath); - - File.WriteAllText(tmpPath, text); - File.Move(tmpPath, path, true); - } - /// /// Gets a random, inoffensive, human-friendly string. /// From f072a6fc40f710dbb30bbfe6b99360714053ee32 Mon Sep 17 00:00:00 2001 From: goat <16760685+goaaats@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:47:06 +0200 Subject: [PATCH 075/120] Update Dalamud/Hooking/Internal/HookProviderPluginScoped.cs Co-authored-by: Haselnussbomber --- Dalamud/Hooking/Internal/HookProviderPluginScoped.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs index 0e7ef4c7b..0878bce28 100644 --- a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs +++ b/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs @@ -80,7 +80,7 @@ internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposab /// public Hook FromSignature(string signature, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate - => this.FromAddress(this.scanner.ScanText(signature), detour); + => this.FromAddress(this.scanner.ScanText(signature), detour, backend); /// public void Dispose() From 173e9a3144d2ab93e9ee190da3fcb6694c6e84ec Mon Sep 17 00:00:00 2001 From: goat Date: Thu, 21 Sep 2023 22:07:09 +0200 Subject: [PATCH 076/120] IHookProvider => IGameInteropProvider --- ...d.cs => GameInteropProviderPluginScoped.cs} | 18 +++++++++--------- ...HookProvider.cs => IGameInteropProvider.cs} | 2 +- Dalamud/Utility/Signatures/SignatureHelper.cs | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) rename Dalamud/Hooking/Internal/{HookProviderPluginScoped.cs => GameInteropProviderPluginScoped.cs} (78%) rename Dalamud/Plugin/Services/{IHookProvider.cs => IGameInteropProvider.cs} (99%) diff --git a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs b/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs similarity index 78% rename from Dalamud/Hooking/Internal/HookProviderPluginScoped.cs rename to Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs index 6fa700cef..d6fc34b10 100644 --- a/Dalamud/Hooking/Internal/HookProviderPluginScoped.cs +++ b/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs @@ -19,9 +19,9 @@ namespace Dalamud.Hooking.Internal; [InterfaceVersion("1.0")] [ServiceManager.ScopedService] #pragma warning disable SA1015 -[ResolveVia] +[ResolveVia] #pragma warning restore SA1015 -internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposable +internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceType, IDisposable { private readonly LocalPlugin plugin; private readonly SigScanner scanner; @@ -29,11 +29,11 @@ internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposab private readonly ConcurrentBag trackedHooks = new(); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Plugin this instance belongs to. /// SigScanner instance for target module. - public HookProviderPluginScoped(LocalPlugin plugin, SigScanner scanner) + public GameInteropProviderPluginScoped(LocalPlugin plugin, SigScanner scanner) { this.plugin = plugin; this.scanner = scanner; @@ -63,23 +63,23 @@ internal class HookProviderPluginScoped : IHookProvider, IServiceType, IDisposab } /// - public Hook FromSymbol(string moduleName, string exportName, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate + public Hook FromSymbol(string moduleName, string exportName, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate { - var hook = Hook.FromSymbol(moduleName, exportName, detour, backend == IHookProvider.HookBackend.MinHook); + var hook = Hook.FromSymbol(moduleName, exportName, detour, backend == IGameInteropProvider.HookBackend.MinHook); this.trackedHooks.Add(hook); return hook; } /// - public Hook FromAddress(IntPtr procAddress, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate + public Hook FromAddress(IntPtr procAddress, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate { - var hook = Hook.FromAddress(procAddress, detour, backend == IHookProvider.HookBackend.MinHook); + var hook = Hook.FromAddress(procAddress, detour, backend == IGameInteropProvider.HookBackend.MinHook); this.trackedHooks.Add(hook); return hook; } /// - public Hook FromSignature(string signature, T detour, IHookProvider.HookBackend backend = IHookProvider.HookBackend.Automatic) where T : Delegate + public Hook FromSignature(string signature, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate => this.FromAddress(this.scanner.ScanText(signature), detour, backend); /// diff --git a/Dalamud/Plugin/Services/IHookProvider.cs b/Dalamud/Plugin/Services/IGameInteropProvider.cs similarity index 99% rename from Dalamud/Plugin/Services/IHookProvider.cs rename to Dalamud/Plugin/Services/IGameInteropProvider.cs index dc7d29913..9451a60eb 100644 --- a/Dalamud/Plugin/Services/IHookProvider.cs +++ b/Dalamud/Plugin/Services/IGameInteropProvider.cs @@ -8,7 +8,7 @@ namespace Dalamud.Plugin.Services; /// /// Service responsible for the creation of hooks. /// -public interface IHookProvider +public interface IGameInteropProvider { /// /// Available hooking backends. diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index 1cfd18330..f011f8121 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -161,7 +161,7 @@ internal static class SignatureHelper continue; } - var hook = creator.Invoke(null, new object?[] { ptr, detour, IHookProvider.HookBackend.Automatic }) as IDalamudHook; + var hook = creator.Invoke(null, new object?[] { ptr, detour, IGameInteropProvider.HookBackend.Automatic }) as IDalamudHook; info.SetValue(self, hook); createdHooks.Add(hook); From e31234ffeccb863b8a24940bf568d6a1906b2c9f Mon Sep 17 00:00:00 2001 From: goat Date: Thu, 21 Sep 2023 22:09:38 +0200 Subject: [PATCH 077/120] prefix methods with Hook to improve clarity --- .../Internal/GameInteropProviderPluginScoped.cs | 12 ++++++------ Dalamud/Plugin/Services/IGameInteropProvider.cs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs b/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs index d6fc34b10..96172e5b2 100644 --- a/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs +++ b/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs @@ -47,7 +47,7 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT } /// - public Hook FromFunctionPointerVariable(IntPtr address, T detour) where T : Delegate + public Hook HookFromFunctionPointerVariable(IntPtr address, T detour) where T : Delegate { var hook = Hook.FromFunctionPointerVariable(address, detour); this.trackedHooks.Add(hook); @@ -55,7 +55,7 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT } /// - public Hook FromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) where T : Delegate + public Hook HookFromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) where T : Delegate { var hook = Hook.FromImport(module, moduleName, functionName, hintOrOrdinal, detour); this.trackedHooks.Add(hook); @@ -63,7 +63,7 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT } /// - public Hook FromSymbol(string moduleName, string exportName, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate + public Hook HookFromSymbol(string moduleName, string exportName, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate { var hook = Hook.FromSymbol(moduleName, exportName, detour, backend == IGameInteropProvider.HookBackend.MinHook); this.trackedHooks.Add(hook); @@ -71,7 +71,7 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT } /// - public Hook FromAddress(IntPtr procAddress, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate + public Hook HookFromAddress(IntPtr procAddress, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate { var hook = Hook.FromAddress(procAddress, detour, backend == IGameInteropProvider.HookBackend.MinHook); this.trackedHooks.Add(hook); @@ -79,8 +79,8 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT } /// - public Hook FromSignature(string signature, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate - => this.FromAddress(this.scanner.ScanText(signature), detour, backend); + public Hook HookFromSignature(string signature, T detour, IGameInteropProvider.HookBackend backend = IGameInteropProvider.HookBackend.Automatic) where T : Delegate + => this.HookFromAddress(this.scanner.ScanText(signature), detour, backend); /// public void Dispose() diff --git a/Dalamud/Plugin/Services/IGameInteropProvider.cs b/Dalamud/Plugin/Services/IGameInteropProvider.cs index 9451a60eb..186663a9e 100644 --- a/Dalamud/Plugin/Services/IGameInteropProvider.cs +++ b/Dalamud/Plugin/Services/IGameInteropProvider.cs @@ -46,7 +46,7 @@ public interface IGameInteropProvider /// Callback function. Delegate must have a same original function prototype. /// The hook with the supplied parameters. /// Delegate of detour. - public Hook FromFunctionPointerVariable(IntPtr address, T detour) where T : Delegate; + public Hook HookFromFunctionPointerVariable(IntPtr address, T detour) where T : Delegate; /// /// Creates a hook by rewriting import table address. @@ -58,7 +58,7 @@ public interface IGameInteropProvider /// Callback function. Delegate must have a same original function prototype. /// The hook with the supplied parameters. /// Delegate of detour. - public Hook FromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) where T : Delegate; + public Hook HookFromImport(ProcessModule? module, string moduleName, string functionName, uint hintOrOrdinal, T detour) where T : Delegate; /// /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. @@ -71,7 +71,7 @@ public interface IGameInteropProvider /// Hooking library to use. /// The hook with the supplied parameters. /// Delegate of detour. - Hook FromSymbol(string moduleName, string exportName, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; + Hook HookFromSymbol(string moduleName, string exportName, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; /// /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. @@ -83,7 +83,7 @@ public interface IGameInteropProvider /// Hooking library to use. /// The hook with the supplied parameters. /// Delegate of detour. - Hook FromAddress(IntPtr procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; + Hook HookFromAddress(IntPtr procAddress, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; /// /// Creates a hook from a signature into the Dalamud target module. @@ -93,5 +93,5 @@ public interface IGameInteropProvider /// Hooking library to use. /// The hook with the supplied parameters. /// Delegate of detour. - Hook FromSignature(string signature, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; + Hook HookFromSignature(string signature, T detour, HookBackend backend = HookBackend.Automatic) where T : Delegate; } From eb2a5f36f9184ce9cb2f4c5e008898c2690794e2 Mon Sep 17 00:00:00 2001 From: goat Date: Thu, 21 Sep 2023 22:11:18 +0200 Subject: [PATCH 078/120] fix spelling inconsistency --- Dalamud/Plugin/Services/IGameInteropProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Plugin/Services/IGameInteropProvider.cs b/Dalamud/Plugin/Services/IGameInteropProvider.cs index 186663a9e..29f42a655 100644 --- a/Dalamud/Plugin/Services/IGameInteropProvider.cs +++ b/Dalamud/Plugin/Services/IGameInteropProvider.cs @@ -36,7 +36,7 @@ public interface IGameInteropProvider /// Initialize members decorated with the . /// Errors for fallible signatures will be logged. /// - /// The object to initialise. + /// The object to initialize. public void InitializeFromAttributes(object self); /// From b742abe77fd0bde0d5cf5657ec28759989bb370c Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:55:16 -0700 Subject: [PATCH 079/120] Add ClientStatePluginScoped (#1384) * Add ClientStatePluginScoped * Restore InvokeSafely * Add InvokeSafely for basic Action types. * Set delegates to null to prevent leaking memory * Resolve Merge --- Dalamud/Game/ClientState/ClientState.cs | 137 +++++++++++++++--- Dalamud/Game/DutyState/DutyState.cs | 2 +- .../Game/Network/Internal/NetworkHandlers.cs | 6 +- .../AgingSteps/EnterTerritoryAgingStep.cs | 4 +- .../AgingSteps/LoginEventAgingStep.cs | 2 +- .../AgingSteps/LogoutEventAgingStep.cs | 2 +- Dalamud/Plugin/Services/IClientState.cs | 8 +- Dalamud/Utility/EventHandlerExtensions.cs | 41 +++++- 8 files changed, 165 insertions(+), 37 deletions(-) diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index cef802c81..baf6f6634 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -8,24 +8,25 @@ using Dalamud.Game.Network.Internal; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.Game; -using Serilog; +using Lumina.Excel.GeneratedSheets; + +using Action = System.Action; namespace Dalamud.Game.ClientState; /// /// This class represents the state of the game client at the time of access. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 internal sealed class ClientState : IDisposable, IServiceType, IClientState { + private static readonly ModuleLog Log = new("ClientState"); + private readonly GameLifecycle lifecycle; private readonly ClientStateAddressResolver address; private readonly Hook setupTerritoryTypeHook; @@ -37,7 +38,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState private readonly NetworkHandlers networkHandlers = Service.Get(); private bool lastConditionNone = true; - private bool lastFramePvP = false; + private bool lastFramePvP; [ServiceManager.ServiceConstructor] private ClientState(SigScanner sigScanner, DalamudStartInfo startInfo, GameLifecycle lifecycle) @@ -63,22 +64,22 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState private delegate IntPtr SetupTerritoryTypeDelegate(IntPtr manager, ushort terriType); /// - public event EventHandler TerritoryChanged; + public event Action? TerritoryChanged; /// - public event EventHandler Login; + public event Action? Login; /// - public event EventHandler Logout; + public event Action? Logout; /// - public event Action EnterPvP; + public event Action? EnterPvP; /// - public event Action LeavePvP; + public event Action? LeavePvP; /// - public event EventHandler CfPop; + public event Action? CfPop; /// public ClientLanguage ClientLanguage { get; } @@ -128,16 +129,16 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState private IntPtr SetupTerritoryTypeDetour(IntPtr manager, ushort terriType) { this.TerritoryType = terriType; - this.TerritoryChanged?.InvokeSafely(this, terriType); + this.TerritoryChanged?.InvokeSafely(terriType); Log.Debug("TerritoryType changed: {0}", terriType); return this.setupTerritoryTypeHook.Original(manager, terriType); } - private void NetworkHandlersOnCfPop(object sender, Lumina.Excel.GeneratedSheets.ContentFinderCondition e) + private void NetworkHandlersOnCfPop(ContentFinderCondition e) { - this.CfPop?.InvokeSafely(this, e); + this.CfPop?.InvokeSafely(e); } private void FrameworkOnOnUpdateEvent(IFramework framework1) @@ -149,12 +150,12 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState if (condition == null || gameGui == null || data == null) return; - if (condition.Any() && this.lastConditionNone == true && this.LocalPlayer != null) + if (condition.Any() && this.lastConditionNone && this.LocalPlayer != null) { Log.Debug("Is login"); this.lastConditionNone = false; this.IsLoggedIn = true; - this.Login?.InvokeSafely(this, null); + this.Login?.InvokeSafely(); gameGui.ResetUiHideState(); this.lifecycle.ResetLogout(); @@ -165,7 +166,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState Log.Debug("Is logout"); this.lastConditionNone = true; this.IsLoggedIn = false; - this.Logout?.InvokeSafely(this, null); + this.Logout?.InvokeSafely(); gameGui.ResetUiHideState(); this.lifecycle.SetLogout(); @@ -189,3 +190,103 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState } } } + +/// +/// Plugin-scoped version of a GameConfig service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class ClientStatePluginScoped : IDisposable, IServiceType, IClientState +{ + [ServiceManager.ServiceDependency] + private readonly ClientState clientStateService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal ClientStatePluginScoped() + { + this.clientStateService.TerritoryChanged += this.TerritoryChangedForward; + this.clientStateService.Login += this.LoginForward; + this.clientStateService.Logout += this.LogoutForward; + this.clientStateService.EnterPvP += this.EnterPvPForward; + this.clientStateService.LeavePvP += this.ExitPvPForward; + this.clientStateService.CfPop += this.ContentFinderPopForward; + } + + /// + public event Action? TerritoryChanged; + + /// + public event Action? Login; + + /// + public event Action? Logout; + + /// + public event Action? EnterPvP; + + /// + public event Action? LeavePvP; + + /// + public event Action? CfPop; + + /// + public ClientLanguage ClientLanguage => this.clientStateService.ClientLanguage; + + /// + public ushort TerritoryType => this.clientStateService.TerritoryType; + + /// + public PlayerCharacter? LocalPlayer => this.clientStateService.LocalPlayer; + + /// + public ulong LocalContentId => this.clientStateService.LocalContentId; + + /// + public bool IsLoggedIn => this.clientStateService.IsLoggedIn; + + /// + public bool IsPvP => this.clientStateService.IsPvP; + + /// + public bool IsPvPExcludingDen => this.clientStateService.IsPvPExcludingDen; + + /// + public bool IsGPosing => this.clientStateService.IsGPosing; + + /// + public void Dispose() + { + this.clientStateService.TerritoryChanged -= this.TerritoryChangedForward; + this.clientStateService.Login -= this.LoginForward; + this.clientStateService.Logout -= this.LogoutForward; + this.clientStateService.EnterPvP -= this.EnterPvPForward; + this.clientStateService.LeavePvP -= this.ExitPvPForward; + this.clientStateService.CfPop -= this.ContentFinderPopForward; + + this.TerritoryChanged = null; + this.Login = null; + this.Logout = null; + this.EnterPvP = null; + this.LeavePvP = null; + this.CfPop = null; + } + + private void TerritoryChangedForward(ushort territoryId) => this.TerritoryChanged?.Invoke(territoryId); + + private void LoginForward() => this.Login?.Invoke(); + + private void LogoutForward() => this.Logout?.Invoke(); + + private void EnterPvPForward() => this.EnterPvP?.Invoke(); + + private void ExitPvPForward() => this.LeavePvP?.Invoke(); + + private void ContentFinderPopForward(ContentFinderCondition cfc) => this.CfPop?.Invoke(cfc); +} diff --git a/Dalamud/Game/DutyState/DutyState.cs b/Dalamud/Game/DutyState/DutyState.cs index c52ceff0f..3890a1f8b 100644 --- a/Dalamud/Game/DutyState/DutyState.cs +++ b/Dalamud/Game/DutyState/DutyState.cs @@ -120,7 +120,7 @@ internal unsafe class DutyState : IDisposable, IServiceType, IDutyState return this.contentDirectorNetworkMessageHook.Original(a1, a2, a3); } - private void TerritoryOnChangedEvent(object? sender, ushort e) + private void TerritoryOnChangedEvent(ushort territoryId) { if (this.IsDutyStarted) { diff --git a/Dalamud/Game/Network/Internal/NetworkHandlers.cs b/Dalamud/Game/Network/Internal/NetworkHandlers.cs index 1ccf6c6d5..77bf99c1b 100644 --- a/Dalamud/Game/Network/Internal/NetworkHandlers.cs +++ b/Dalamud/Game/Network/Internal/NetworkHandlers.cs @@ -44,7 +44,7 @@ internal class NetworkHandlers : IDisposable, IServiceType private NetworkHandlers(GameNetwork gameNetwork) { this.uploader = new UniversalisMarketBoardUploader(); - this.CfPop = (_, _) => { }; + this.CfPop = _ => { }; this.messages = Observable.Create(observer => { @@ -75,7 +75,7 @@ internal class NetworkHandlers : IDisposable, IServiceType /// /// Event which gets fired when a duty is ready. /// - public event EventHandler CfPop; + public event Action CfPop; /// /// Disposes of managed and unmanaged resources. @@ -430,7 +430,7 @@ internal class NetworkHandlers : IDisposable, IServiceType Service.GetNullable()?.Print($"Duty pop: {cfcName}"); } - this.CfPop.InvokeSafely(this, cfCondition); + this.CfPop.InvokeSafely(cfCondition); }).ContinueWith( task => Log.Error(task.Exception, "CfPop.Invoke failed"), TaskContinuationOptions.OnlyOnFaulted); diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/EnterTerritoryAgingStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/EnterTerritoryAgingStep.cs index d301cb1ff..4f5c758d6 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/EnterTerritoryAgingStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/EnterTerritoryAgingStep.cs @@ -59,9 +59,9 @@ internal class EnterTerritoryAgingStep : IAgingStep this.subscribed = false; } - private void ClientStateOnTerritoryChanged(object sender, ushort e) + private void ClientStateOnTerritoryChanged(ushort territoryId) { - if (e == this.territory) + if (territoryId == this.territory) { this.hasPassed = true; } diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LoginEventAgingStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LoginEventAgingStep.cs index c1dba389f..23b0b903a 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LoginEventAgingStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LoginEventAgingStep.cs @@ -51,7 +51,7 @@ internal class LoginEventAgingStep : IAgingStep } } - private void ClientStateOnOnLogin(object sender, EventArgs e) + private void ClientStateOnOnLogin() { this.hasPassed = true; } diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LogoutEventAgingStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LogoutEventAgingStep.cs index 060c0bcc8..c4c6ebfce 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LogoutEventAgingStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/LogoutEventAgingStep.cs @@ -51,7 +51,7 @@ internal class LogoutEventAgingStep : IAgingStep } } - private void ClientStateOnOnLogout(object sender, EventArgs e) + private void ClientStateOnOnLogout() { this.hasPassed = true; } diff --git a/Dalamud/Plugin/Services/IClientState.cs b/Dalamud/Plugin/Services/IClientState.cs index 881cad841..652a6c888 100644 --- a/Dalamud/Plugin/Services/IClientState.cs +++ b/Dalamud/Plugin/Services/IClientState.cs @@ -12,17 +12,17 @@ public interface IClientState /// /// Event that gets fired when the current Territory changes. /// - public event EventHandler TerritoryChanged; + public event Action TerritoryChanged; /// /// Event that fires when a character is logging in, and the local character object is available. /// - public event EventHandler Login; + public event Action Login; /// /// Event that fires when a character is logging out. /// - public event EventHandler Logout; + public event Action Logout; /// /// Event that fires when a character is entering PvP. @@ -37,7 +37,7 @@ public interface IClientState /// /// Event that gets fired when a duty is ready. /// - public event EventHandler CfPop; + public event Action CfPop; /// /// Gets the language of the client. diff --git a/Dalamud/Utility/EventHandlerExtensions.cs b/Dalamud/Utility/EventHandlerExtensions.cs index eefd245bb..d05ad6ea5 100644 --- a/Dalamud/Utility/EventHandlerExtensions.cs +++ b/Dalamud/Utility/EventHandlerExtensions.cs @@ -1,12 +1,9 @@ -using System; using System.Linq; using Dalamud.Game; using Dalamud.Plugin.Services; using Serilog; -using static Dalamud.Game.Framework; - namespace Dalamud.Utility; /// @@ -21,7 +18,7 @@ internal static class EventHandlerExtensions /// The EventHandler in question. /// Default sender for Invoke equivalent. /// Default EventArgs for Invoke equivalent. - public static void InvokeSafely(this EventHandler eh, object sender, EventArgs e) + public static void InvokeSafely(this EventHandler? eh, object sender, EventArgs e) { if (eh == null) return; @@ -40,7 +37,7 @@ internal static class EventHandlerExtensions /// Default sender for Invoke equivalent. /// Default EventArgs for Invoke equivalent. /// Type of EventArgs. - public static void InvokeSafely(this EventHandler eh, object sender, T e) + public static void InvokeSafely(this EventHandler? eh, object sender, T e) { if (eh == null) return; @@ -56,7 +53,7 @@ internal static class EventHandlerExtensions /// of a thrown Exception inside of an invocation. /// /// The Action in question. - public static void InvokeSafely(this Action act) + public static void InvokeSafely(this Action? act) { if (act == null) return; @@ -67,13 +64,31 @@ internal static class EventHandlerExtensions } } + /// + /// Replacement for Invoke() on event Actions to catch exceptions that stop event propagation in case + /// of a thrown Exception inside of an invocation. + /// + /// The Action in question. + /// Templated argument for Action. + /// Type of Action args. + public static void InvokeSafely(this Action? act, T argument) + { + if (act == null) + return; + + foreach (var action in act.GetInvocationList().Cast>()) + { + HandleInvoke(action, argument); + } + } + /// /// Replacement for Invoke() on OnUpdateDelegate to catch exceptions that stop event propagation in case /// of a thrown Exception inside of an invocation. /// /// The OnUpdateDelegate in question. /// Framework to be passed on to OnUpdateDelegate. - public static void InvokeSafely(this IFramework.OnUpdateDelegate updateDelegate, Framework framework) + public static void InvokeSafely(this IFramework.OnUpdateDelegate? updateDelegate, Framework framework) { if (updateDelegate == null) return; @@ -95,4 +110,16 @@ internal static class EventHandlerExtensions Log.Error(ex, "Exception during raise of {handler}", act.Method); } } + + private static void HandleInvoke(Action act, T argument) + { + try + { + act(argument); + } + catch (Exception ex) + { + Log.Error(ex, "Exception during raise of {handler}", act.Method); + } + } } From 43abb12710e1193f6e3ba898a932b3583826baba Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:55:56 -0700 Subject: [PATCH 080/120] Add GameConfigPluginScoped (#1383) * Add GameConfigPluginScoped * Proposed Resolution to sub-object events * Nullify delegates to prevent memory leaks --- Dalamud/Game/Config/GameConfig.cs | 224 ++++++++++++++++++++++- Dalamud/Game/Config/GameConfigSection.cs | 2 +- Dalamud/Plugin/Services/IGameConfig.cs | 17 +- 3 files changed, 235 insertions(+), 8 deletions(-) diff --git a/Dalamud/Game/Config/GameConfig.cs b/Dalamud/Game/Config/GameConfig.cs index b77b9c4af..831c1157b 100644 --- a/Dalamud/Game/Config/GameConfig.cs +++ b/Dalamud/Game/Config/GameConfig.cs @@ -12,11 +12,7 @@ namespace Dalamud.Game.Config; /// This class represents the game's configuration. /// [InterfaceVersion("1.0")] -[PluginInterface] [ServiceManager.EarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable { private readonly GameConfigAddressResolver address = new(); @@ -36,15 +32,30 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable this.address.Setup(sigScanner); this.configChangeHook = Hook.FromAddress(this.address.ConfigChangeAddress, this.OnConfigChanged); - this.configChangeHook?.Enable(); + this.configChangeHook.Enable(); }); } private unsafe delegate nint ConfigChangeDelegate(ConfigBase* configBase, ConfigEntry* configEntry); /// - public event EventHandler Changed; + public event EventHandler? Changed; + + /// + /// Unused internally, used as a proxy for System.Changed via GameConfigPluginScoped + /// + public event EventHandler? SystemChanged; + /// + /// Unused internally, used as a proxy for UiConfig.Changed via GameConfigPluginScoped + /// + public event EventHandler? UiConfigChanged; + + /// + /// Unused internally, used as a proxy for UiControl.Changed via GameConfigPluginScoped + /// + public event EventHandler? UiControlChanged; + /// public GameConfigSection System { get; private set; } @@ -192,3 +203,204 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable return returnValue; } } + +/// +/// Plugin-scoped version of a GameConfig service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class GameConfigPluginScoped : IDisposable, IServiceType, IGameConfig +{ + [ServiceManager.ServiceDependency] + private readonly GameConfig gameConfigService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal GameConfigPluginScoped() + { + this.gameConfigService.Changed += this.ConfigChangedForward; + this.gameConfigService.System.Changed += this.SystemConfigChangedForward; + this.gameConfigService.UiConfig.Changed += this.UiConfigConfigChangedForward; + this.gameConfigService.UiControl.Changed += this.UiControlConfigChangedForward; + } + + /// + public event EventHandler? Changed; + + /// + public event EventHandler? SystemChanged; + + /// + public event EventHandler? UiConfigChanged; + + /// + public event EventHandler? UiControlChanged; + + /// + public GameConfigSection System => this.gameConfigService.System; + + /// + public GameConfigSection UiConfig => this.gameConfigService.UiConfig; + + /// + public GameConfigSection UiControl => this.gameConfigService.UiControl; + + /// + public void Dispose() + { + this.gameConfigService.Changed -= this.ConfigChangedForward; + this.gameConfigService.System.Changed -= this.SystemConfigChangedForward; + this.gameConfigService.UiConfig.Changed -= this.UiConfigConfigChangedForward; + this.gameConfigService.UiControl.Changed -= this.UiControlConfigChangedForward; + + this.Changed = null; + this.SystemChanged = null; + this.UiConfigChanged = null; + this.UiControlChanged = null; + } + + /// + public bool TryGet(SystemConfigOption option, out bool value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(SystemConfigOption option, out uint value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(SystemConfigOption option, out float value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(SystemConfigOption option, out string value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(SystemConfigOption option, out UIntConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(SystemConfigOption option, out FloatConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(SystemConfigOption option, out StringConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(UiConfigOption option, out bool value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiConfigOption option, out uint value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiConfigOption option, out float value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiConfigOption option, out string value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiConfigOption option, out UIntConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(UiConfigOption option, out FloatConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(UiConfigOption option, out StringConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(UiControlOption option, out bool value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiControlOption option, out uint value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiControlOption option, out float value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiControlOption option, out string value) + => this.gameConfigService.TryGet(option, out value); + + /// + public bool TryGet(UiControlOption option, out UIntConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(UiControlOption option, out FloatConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public bool TryGet(UiControlOption option, out StringConfigProperties? properties) + => this.gameConfigService.TryGet(option, out properties); + + /// + public void Set(SystemConfigOption option, bool value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(SystemConfigOption option, uint value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(SystemConfigOption option, float value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(SystemConfigOption option, string value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiConfigOption option, bool value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiConfigOption option, uint value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiConfigOption option, float value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiConfigOption option, string value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiControlOption option, bool value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiControlOption option, uint value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiControlOption option, float value) + => this.gameConfigService.Set(option, value); + + /// + public void Set(UiControlOption option, string value) + => this.gameConfigService.Set(option, value); + + private void ConfigChangedForward(object sender, ConfigChangeEvent data) => this.Changed?.Invoke(sender, data); + + private void SystemConfigChangedForward(object sender, ConfigChangeEvent data) => this.SystemChanged?.Invoke(sender, data); + + private void UiConfigConfigChangedForward(object sender, ConfigChangeEvent data) => this.UiConfigChanged?.Invoke(sender, data); + + private void UiControlConfigChangedForward(object sender, ConfigChangeEvent data) => this.UiControlChanged?.Invoke(sender, data); +} diff --git a/Dalamud/Game/Config/GameConfigSection.cs b/Dalamud/Game/Config/GameConfigSection.cs index ea79a7fc8..31e4a0b3f 100644 --- a/Dalamud/Game/Config/GameConfigSection.cs +++ b/Dalamud/Game/Config/GameConfigSection.cs @@ -51,7 +51,7 @@ public class GameConfigSection /// /// Event which is fired when a game config option is changed within the section. /// - public event EventHandler? Changed; + internal event EventHandler? Changed; /// /// Gets the number of config entries contained within the section. diff --git a/Dalamud/Plugin/Services/IGameConfig.cs b/Dalamud/Plugin/Services/IGameConfig.cs index 69a611114..8e9b48d83 100644 --- a/Dalamud/Plugin/Services/IGameConfig.cs +++ b/Dalamud/Plugin/Services/IGameConfig.cs @@ -12,10 +12,25 @@ namespace Dalamud.Plugin.Services; public interface IGameConfig { /// - /// Event which is fired when a game config option is changed. + /// Event which is fired when any game config option is changed. /// public event EventHandler Changed; + /// + /// Event which is fired when a system config option is changed. + /// + public event EventHandler SystemChanged; + + /// + /// Event which is fired when a UiConfig option is changed. + /// + public event EventHandler UiConfigChanged; + + /// + /// Event which is fired when a UiControl config option is changed. + /// + public event EventHandler UiControlChanged; + /// /// Gets the collection of config options that persist between characters. /// From 9181e1119564f21fbcbcf4265fbe1d74fe8f7470 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:59:04 -0700 Subject: [PATCH 081/120] Remove Obsoletes --- Dalamud/Game/ClientState/Buddy/BuddyList.cs | 12 -- .../Game/ClientState/GamePad/GamepadState.cs | 48 -------- .../Game/ClientState/Objects/TargetManager.cs | 110 +----------------- .../Internal/DXGI/SwapChainSigResolver.cs | 34 ------ .../Interface/ImGuiFileDialog/FileDialog.cs | 10 -- Dalamud/Interface/Windowing/WindowSystem.cs | 8 -- 6 files changed, 5 insertions(+), 217 deletions(-) delete mode 100644 Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs diff --git a/Dalamud/Game/ClientState/Buddy/BuddyList.cs b/Dalamud/Game/ClientState/Buddy/BuddyList.cs index 489e75bc3..5d0098187 100644 --- a/Dalamud/Game/ClientState/Buddy/BuddyList.cs +++ b/Dalamud/Game/ClientState/Buddy/BuddyList.cs @@ -55,18 +55,6 @@ internal sealed partial class BuddyList : IServiceType, IBuddyList } } - /// - /// Gets a value indicating whether the local player's companion is present. - /// - [Obsolete("Use CompanionBuddy != null", false)] - public bool CompanionBuddyPresent => this.CompanionBuddy != null; - - /// - /// Gets a value indicating whether the local player's pet is present. - /// - [Obsolete("Use PetBuddy != null", false)] - public bool PetBuddyPresent => this.PetBuddy != null; - /// public BuddyMember? CompanionBuddy { diff --git a/Dalamud/Game/ClientState/GamePad/GamepadState.cs b/Dalamud/Game/ClientState/GamePad/GamepadState.cs index 8acb6ada5..b03db6df2 100644 --- a/Dalamud/Game/ClientState/GamePad/GamepadState.cs +++ b/Dalamud/Game/ClientState/GamePad/GamepadState.cs @@ -55,54 +55,6 @@ internal unsafe class GamepadState : IDisposable, IServiceType, IGamepadState public Vector2 RightStick => new(this.rightStickX, this.rightStickY); - /// - /// Gets the state of the left analogue stick in the left direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.LeftStick.X", false)] - public float LeftStickLeft => this.leftStickX < 0 ? -this.leftStickX / 100f : 0; - - /// - /// Gets the state of the left analogue stick in the right direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.LeftStick.X", false)] - public float LeftStickRight => this.leftStickX > 0 ? this.leftStickX / 100f : 0; - - /// - /// Gets the state of the left analogue stick in the up direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.LeftStick.Y", false)] - public float LeftStickUp => this.leftStickY > 0 ? this.leftStickY / 100f : 0; - - /// - /// Gets the state of the left analogue stick in the down direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.LeftStick.Y", false)] - public float LeftStickDown => this.leftStickY < 0 ? -this.leftStickY / 100f : 0; - - /// - /// Gets the state of the right analogue stick in the left direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.RightStick.X", false)] - public float RightStickLeft => this.rightStickX < 0 ? -this.rightStickX / 100f : 0; - - /// - /// Gets the state of the right analogue stick in the right direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.RightStick.X", false)] - public float RightStickRight => this.rightStickX > 0 ? this.rightStickX / 100f : 0; - - /// - /// Gets the state of the right analogue stick in the up direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.RightStick.Y", false)] - public float RightStickUp => this.rightStickY > 0 ? this.rightStickY / 100f : 0; - - /// - /// Gets the state of the right analogue stick in the down direction between 0 (not tilted) and 1 (max tilt). - /// - [Obsolete("Use IGamepadState.RightStick.Y", false)] - public float RightStickDown => this.rightStickY < 0 ? -this.rightStickY / 100f : 0; - /// /// Gets buttons pressed bitmask, set once when the button is pressed. See for the mapping. /// diff --git a/Dalamud/Game/ClientState/Objects/TargetManager.cs b/Dalamud/Game/ClientState/Objects/TargetManager.cs index a821ba806..fcb242c1e 100644 --- a/Dalamud/Game/ClientState/Objects/TargetManager.cs +++ b/Dalamud/Game/ClientState/Objects/TargetManager.cs @@ -39,35 +39,35 @@ internal sealed unsafe class TargetManager : IServiceType, ITargetManager public GameObject? Target { get => this.objectTable.CreateObjectReference((IntPtr)Struct->Target); - set => this.SetTarget(value); + set => Struct->Target = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)value?.Address; } /// public GameObject? MouseOverTarget { get => this.objectTable.CreateObjectReference((IntPtr)Struct->MouseOverTarget); - set => this.SetMouseOverTarget(value); + set => Struct->MouseOverTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)value?.Address; } /// public GameObject? FocusTarget { get => this.objectTable.CreateObjectReference((IntPtr)Struct->FocusTarget); - set => this.SetFocusTarget(value); + set => Struct->FocusTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)value?.Address; } /// public GameObject? PreviousTarget { get => this.objectTable.CreateObjectReference((IntPtr)Struct->PreviousTarget); - set => this.SetPreviousTarget(value); + set => Struct->PreviousTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)value?.Address; } /// public GameObject? SoftTarget { get => this.objectTable.CreateObjectReference((IntPtr)Struct->SoftTarget); - set => this.SetSoftTarget(value); + set => Struct->SoftTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)value?.Address; } /// @@ -85,104 +85,4 @@ internal sealed unsafe class TargetManager : IServiceType, ITargetManager } private FFXIVClientStructs.FFXIV.Client.Game.Control.TargetSystem* Struct => (FFXIVClientStructs.FFXIV.Client.Game.Control.TargetSystem*)this.Address; - - /// - /// Sets the current target. - /// - /// Actor to target. - [Obsolete("Use Target Property", false)] - public void SetTarget(GameObject? actor) => this.SetTarget(actor?.Address ?? IntPtr.Zero); - - /// - /// Sets the mouseover target. - /// - /// Actor to target. - [Obsolete("Use MouseOverTarget Property", false)] - public void SetMouseOverTarget(GameObject? actor) => this.SetMouseOverTarget(actor?.Address ?? IntPtr.Zero); - - /// - /// Sets the focus target. - /// - /// Actor to target. - [Obsolete("Use FocusTarget Property", false)] - public void SetFocusTarget(GameObject? actor) => this.SetFocusTarget(actor?.Address ?? IntPtr.Zero); - - /// - /// Sets the previous target. - /// - /// Actor to target. - [Obsolete("Use PreviousTarget Property", false)] - public void SetPreviousTarget(GameObject? actor) => this.SetTarget(actor?.Address ?? IntPtr.Zero); - - /// - /// Sets the soft target. - /// - /// Actor to target. - [Obsolete("Use SoftTarget Property", false)] - public void SetSoftTarget(GameObject? actor) => this.SetTarget(actor?.Address ?? IntPtr.Zero); - - /// - /// Sets the current target. - /// - /// Actor (address) to target. - [Obsolete("Use Target Property", false)] - public void SetTarget(IntPtr actorAddress) => Struct->Target = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)actorAddress; - - /// - /// Sets the mouseover target. - /// - /// Actor (address) to target. - [Obsolete("Use MouseOverTarget Property", false)] - public void SetMouseOverTarget(IntPtr actorAddress) => Struct->MouseOverTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)actorAddress; - - /// - /// Sets the focus target. - /// - /// Actor (address) to target. - [Obsolete("Use FocusTarget Property", false)] - public void SetFocusTarget(IntPtr actorAddress) => Struct->FocusTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)actorAddress; - - /// - /// Sets the previous target. - /// - /// Actor (address) to target. - [Obsolete("Use PreviousTarget Property", false)] - public void SetPreviousTarget(IntPtr actorAddress) => Struct->PreviousTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)actorAddress; - - /// - /// Sets the soft target. - /// - /// Actor (address) to target. - [Obsolete("Use SoftTarget Property", false)] - public void SetSoftTarget(IntPtr actorAddress) => Struct->SoftTarget = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)actorAddress; - - /// - /// Clears the current target. - /// - [Obsolete("Use Target Property", false)] - public void ClearTarget() => this.SetTarget(IntPtr.Zero); - - /// - /// Clears the mouseover target. - /// - [Obsolete("Use MouseOverTarget Property", false)] - public void ClearMouseOverTarget() => this.SetMouseOverTarget(IntPtr.Zero); - - /// - /// Clears the focus target. - /// - [Obsolete("Use FocusTarget Property", false)] - public void ClearFocusTarget() => this.SetFocusTarget(IntPtr.Zero); - - /// - /// Clears the previous target. - /// - [Obsolete("Use PreviousTarget Property", false)] - public void ClearPreviousTarget() => this.SetPreviousTarget(IntPtr.Zero); - - /// - /// Clears the soft target. - /// - [Obsolete("Use SoftTarget Property", false)] - public void ClearSoftTarget() => this.SetSoftTarget(IntPtr.Zero); } diff --git a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs deleted file mode 100644 index a2fc08646..000000000 --- a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Diagnostics; -using System.Linq; - -using Serilog; - -namespace Dalamud.Game.Internal.DXGI; - -/// -/// The address resolver for native D3D11 methods to facilitate displaying the Dalamud UI. -/// -[Obsolete("This has been deprecated in favor of the VTable resolver.")] -internal sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver -{ - /// - public IntPtr Present { get; set; } - - /// - public IntPtr ResizeBuffers { get; set; } - - /// - protected override void Setup64Bit(SigScanner sig) - { - var module = Process.GetCurrentProcess().Modules.Cast().First(m => m.ModuleName == "dxgi.dll"); - - Log.Debug($"Found DXGI: 0x{module.BaseAddress.ToInt64():X}"); - - var scanner = new SigScanner(module); - - // This(code after the function head - offset of it) was picked to avoid running into issues with other hooks being installed into this function. - this.Present = scanner.ScanModule("41 8B F0 8B FA 89 54 24 ?? 48 8B D9 48 89 4D ?? C6 44 24 ?? 00") - 0x37; - - this.ResizeBuffers = scanner.ScanModule("48 8B C4 55 41 54 41 55 41 56 41 57 48 8D 68 B1 48 81 EC ?? ?? ?? ?? 48 C7 45 ?? ?? ?? ?? ?? 48 89 58 10 48 89 70 18 48 89 78 20 45 8B F9 45 8B E0 44 8B EA 48 8B F9 8B 45 7F 89 44 24 30 8B 75 77 89 74 24 28 44 89 4C 24"); - } -} diff --git a/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs b/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs index aec5e9af4..411f203cc 100644 --- a/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs +++ b/Dalamud/Interface/ImGuiFileDialog/FileDialog.cs @@ -123,16 +123,6 @@ public partial class FileDialog return this.isOk; } - /// - /// Gets the result of the selection. - /// - /// The result of the selection (file or folder path). If multiple entries were selected, they are separated with commas. - [Obsolete("Use GetResults() instead.", true)] - public string GetResult() - { - return string.Join(',', this.GetResults()); - } - /// /// Gets the result of the selection. /// diff --git a/Dalamud/Interface/Windowing/WindowSystem.cs b/Dalamud/Interface/Windowing/WindowSystem.cs index 8e12d8f68..3e2a95a8d 100644 --- a/Dalamud/Interface/Windowing/WindowSystem.cs +++ b/Dalamud/Interface/Windowing/WindowSystem.cs @@ -94,14 +94,6 @@ public class WindowSystem /// public void RemoveAllWindows() => this.windows.Clear(); - /// - /// Get a window by name. - /// - /// The name of the . - /// The object with matching name or null. - [Obsolete("WindowSystem does not own your window - you should store a reference to it and use that instead.")] - public Window? GetWindow(string windowName) => this.windows.FirstOrDefault(w => w.WindowName == windowName); - /// /// Draw all registered windows using ImGui. /// From 64caf77a32d46482a3ad1d7e8f5530a7421edb23 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Fri, 22 Sep 2023 14:27:13 +0200 Subject: [PATCH 082/120] Update ClientStructs --- lib/FFXIVClientStructs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index fd5ba8a27..a1ddff097 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit fd5ba8a27ec911a69eeb93ceb0202091279dfceb +Subproject commit a1ddff0974729a2e984d8cc1dc007eff19bd74ab From 4f8de2e20592f9d3b0c87b38bcfb5626e62475ec Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Fri, 22 Sep 2023 17:01:10 -0700 Subject: [PATCH 083/120] Obsolete (static) PluginLog for future removal - Mark PluginLog as obsoleted and pending removal, encouraging users to switch to IPluginLog. - Remove internal references to PluginLog. --- Dalamud.CorePlugin/PluginImpl.cs | 11 ++++++----- Dalamud/Logging/PluginLog.cs | 8 ++++++-- Dalamud/Utility/Signatures/SignatureHelper.cs | 9 +++------ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Dalamud.CorePlugin/PluginImpl.cs b/Dalamud.CorePlugin/PluginImpl.cs index 2f76a1087..e2b373d42 100644 --- a/Dalamud.CorePlugin/PluginImpl.cs +++ b/Dalamud.CorePlugin/PluginImpl.cs @@ -1,10 +1,8 @@ using System; using System.IO; - using Dalamud.Configuration.Internal; using Dalamud.Game.Command; using Dalamud.Interface.Windowing; -using Dalamud.Logging; using Dalamud.Plugin; using Dalamud.Plugin.Services; using Dalamud.Utility; @@ -52,6 +50,8 @@ namespace Dalamud.CorePlugin private readonly WindowSystem windowSystem = new("Dalamud.CorePlugin"); private Localization localization; + private IPluginLog pluginLog; + /// /// Initializes a new instance of the class. /// @@ -63,6 +63,7 @@ namespace Dalamud.CorePlugin { // this.InitLoc(); this.Interface = pluginInterface; + this.pluginLog = log; this.windowSystem.AddWindow(new PluginWindow()); @@ -76,7 +77,7 @@ namespace Dalamud.CorePlugin } catch (Exception ex) { - PluginLog.Error(ex, "kaboom"); + log.Error(ex, "kaboom"); } } @@ -130,13 +131,13 @@ namespace Dalamud.CorePlugin } catch (Exception ex) { - PluginLog.Error(ex, "Boom"); + this.pluginLog.Error(ex, "Boom"); } } private void OnCommand(string command, string args) { - PluginLog.Information("Command called!"); + this.pluginLog.Information("Command called!"); // this.window.IsOpen = true; } diff --git a/Dalamud/Logging/PluginLog.cs b/Dalamud/Logging/PluginLog.cs index 3ac98f15a..c3fe0c808 100644 --- a/Dalamud/Logging/PluginLog.cs +++ b/Dalamud/Logging/PluginLog.cs @@ -1,6 +1,5 @@ -using System; using System.Reflection; - +using Dalamud.Plugin.Services; using Serilog; using Serilog.Events; @@ -9,6 +8,11 @@ namespace Dalamud.Logging; /// /// Class offering various static methods to allow for logging in plugins. /// +/// +/// PluginLog has been obsoleted and replaced by the service. Developers are encouraged to +/// move over as soon as reasonably possible for performance reasons. +/// +[Obsolete("Static PluginLog will be removed in API 10. Developers should use IPluginLog.")] public static class PluginLog { #region "Log" prefixed Serilog style methods diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index bd99b8515..20b45e7fb 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -1,11 +1,8 @@ -using System; -using System.Linq; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; - using Dalamud.Game; using Dalamud.Hooking; -using Dalamud.Logging; using Dalamud.Utility.Signatures.Wrappers; using Serilog; @@ -23,7 +20,7 @@ public static class SignatureHelper /// . /// /// The object to initialise. - /// If warnings should be logged using . + /// If warnings should be logged. public static void Initialise(object self, bool log = true) { var scanner = Service.Get(); @@ -61,7 +58,7 @@ public static class SignatureHelper : message; if (fallible) { - PluginLog.Warning(errorMsg); + Log.Warning(errorMsg); } else { From 3618a510d0d56b70c0cd83a02297d321949d5e49 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Fri, 22 Sep 2023 19:17:00 -0700 Subject: [PATCH 084/120] Make Custom Repo warning orange - Easier on the eyes, allegedly. --- .../Widgets/ThirdRepoSettingsEntry.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs index 617cbb045..afebeaedb 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using System.Threading.Tasks; - using CheapLoc; using Dalamud.Configuration; using Dalamud.Configuration.Internal; @@ -80,25 +78,28 @@ public class ThirdRepoSettingsEntry : SettingsEntry var disclaimerDismissed = config.ThirdRepoSpeedbumpDismissed.Value; ImGui.PushFont(InterfaceManager.IconFont); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, FontAwesomeIcon.ExclamationTriangle.ToIconString()); + ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudOrange); + ImGuiHelpers.SafeTextWrapped(FontAwesomeIcon.ExclamationTriangle.ToIconString()); ImGui.PopFont(); ImGui.SameLine(); ImGuiHelpers.ScaledDummy(2); ImGui.SameLine(); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarningReadThis", "READ THIS FIRST!")); + ImGuiHelpers.SafeTextWrapped(Loc.Localize("DalamudSettingCustomRepoWarningReadThis", "READ THIS FIRST!")); ImGui.SameLine(); ImGuiHelpers.ScaledDummy(2); ImGui.SameLine(); ImGui.PushFont(InterfaceManager.IconFont); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, FontAwesomeIcon.ExclamationTriangle.ToIconString()); + ImGuiHelpers.SafeTextWrapped(FontAwesomeIcon.ExclamationTriangle.ToIconString()); ImGui.PopFont(); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning", "We cannot take any responsibility for custom plugins and repositories.")); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning5", "If someone told you to copy/paste something here, it's very possible that you are being scammed or taken advantage of.")); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning2", "Plugins have full control over your PC, like any other program, and may cause harm or crashes.")); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning4", "They can delete your character, steal your FC or Discord account, and burn down your house.")); - ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("DalamudSettingCustomRepoWarning3", "Please make absolutely sure that you only install plugins from developers you trust.")); + ImGuiHelpers.SafeTextWrapped(Loc.Localize("DalamudSettingCustomRepoWarning", "We cannot take any responsibility for custom plugins and repositories.")); + ImGuiHelpers.SafeTextWrapped(Loc.Localize("DalamudSettingCustomRepoWarning5", "If someone told you to copy/paste something here, it's very possible that you are being scammed or taken advantage of.")); + ImGuiHelpers.SafeTextWrapped(Loc.Localize("DalamudSettingCustomRepoWarning2", "Plugins have full control over your PC, like any other program, and may cause harm or crashes.")); + ImGuiHelpers.SafeTextWrapped(Loc.Localize("DalamudSettingCustomRepoWarning4", "They can delete your character, steal your FC or Discord account, and burn down your house.")); + ImGuiHelpers.SafeTextWrapped(Loc.Localize("DalamudSettingCustomRepoWarning3", "Please make absolutely sure that you only install plugins from developers you trust.")); + ImGui.PopStyleColor(); + if (!disclaimerDismissed) { const int speedbumpTime = 15; From d29422bc507582f1cc031880937f36b567ec8792 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Fri, 22 Sep 2023 23:22:59 -0700 Subject: [PATCH 085/120] Add IPluginLog#Info - Shorthand for information log lines, because typing out `Information` is too much. --- Dalamud/Logging/ScopedPluginLogService.cs | 12 +++++++++--- Dalamud/Plugin/Services/IPluginLog.cs | 6 ++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Dalamud/Logging/ScopedPluginLogService.cs b/Dalamud/Logging/ScopedPluginLogService.cs index 8c502fcf0..d6bb1f82d 100644 --- a/Dalamud/Logging/ScopedPluginLogService.cs +++ b/Dalamud/Logging/ScopedPluginLogService.cs @@ -1,6 +1,4 @@ -using System; - -using Dalamud.IoC; +using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Services; @@ -90,6 +88,14 @@ public class ScopedPluginLogService : IServiceType, IPluginLog, IDisposable /// public void Information(Exception? exception, string messageTemplate, params object[] values) => this.Write(LogEventLevel.Information, exception, messageTemplate, values); + + /// + public void Info(string messageTemplate, params object[] values) => + this.Information(messageTemplate, values); + + /// + public void Info(Exception? exception, string messageTemplate, params object[] values) => + this.Information(exception, messageTemplate, values); /// public void Debug(string messageTemplate, params object[] values) => diff --git a/Dalamud/Plugin/Services/IPluginLog.cs b/Dalamud/Plugin/Services/IPluginLog.cs index 62f9e8728..d16e985af 100644 --- a/Dalamud/Plugin/Services/IPluginLog.cs +++ b/Dalamud/Plugin/Services/IPluginLog.cs @@ -76,6 +76,12 @@ public interface IPluginLog /// /// An (optional) exception that should be recorded alongside this event. void Information(Exception? exception, string messageTemplate, params object[] values); + + /// + void Info(string messageTemplate, params object[] values); + + /// + void Info(Exception? exception, string messageTemplate, params object[] values); /// /// Log a message to the Dalamud log for this plugin. This log level should be From 1304c54effb42535dc1a0b78b9b0049ffa9c0ec6 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 10:39:29 +0200 Subject: [PATCH 086/120] docs fixed --- Dalamud/Plugin/Services/IGameInteropProvider.cs | 4 +++- Dalamud/Utility/Signatures/SignatureHelper.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Dalamud/Plugin/Services/IGameInteropProvider.cs b/Dalamud/Plugin/Services/IGameInteropProvider.cs index 29f42a655..217e08445 100644 --- a/Dalamud/Plugin/Services/IGameInteropProvider.cs +++ b/Dalamud/Plugin/Services/IGameInteropProvider.cs @@ -34,13 +34,15 @@ public interface IGameInteropProvider /// /// Initialize members decorated with the . + /// Initialize any delegate members decorated with the . + /// Fill out any IntPtr members decorated with the with the resolved address. /// Errors for fallible signatures will be logged. /// /// The object to initialize. public void InitializeFromAttributes(object self); /// - /// Creates a hook by rewriting import table address. + /// Creates a hook by replacing the original address with an address pointing to a newly created jump to the detour. /// /// A memory address to install a hook. /// Callback function. Delegate must have a same original function prototype. diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index f011f8121..cabe672ce 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -21,10 +21,10 @@ internal static class SignatureHelper private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; /// - /// Initialises an object's fields and properties that are annotated with a + /// Initializes an object's fields and properties that are annotated with a /// . /// - /// The object to initialise. + /// The object to initialize. /// If warnings should be logged using . /// Collection of created IDalamudHooks. internal static IEnumerable Initialize(object self, bool log = true) From c55b93d3c2bd6fe3b71919d5c873028fc6de7adf Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 11:17:53 +0200 Subject: [PATCH 087/120] chore: remove IDalamudPlugin.Name --- Dalamud.CorePlugin/PluginImpl.cs | 9 ++------- Dalamud/Plugin/IDalamudPlugin.cs | 4 ---- Dalamud/Plugin/Internal/Types/LocalPlugin.cs | 7 ------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/Dalamud.CorePlugin/PluginImpl.cs b/Dalamud.CorePlugin/PluginImpl.cs index e2b373d42..5ed672f2d 100644 --- a/Dalamud.CorePlugin/PluginImpl.cs +++ b/Dalamud.CorePlugin/PluginImpl.cs @@ -1,5 +1,6 @@ using System; using System.IO; + using Dalamud.Configuration.Internal; using Dalamud.Game.Command; using Dalamud.Interface.Windowing; @@ -37,9 +38,6 @@ namespace Dalamud.CorePlugin { } - /// - public string Name => "Dalamud.CorePlugin"; - /// public void Dispose() { @@ -71,7 +69,7 @@ namespace Dalamud.CorePlugin this.Interface.UiBuilder.OpenConfigUi += this.OnOpenConfigUi; this.Interface.UiBuilder.OpenMainUi += this.OnOpenMainUi; - Service.Get().AddHandler("/coreplug", new(this.OnCommand) { HelpMessage = $"Access the {this.Name} plugin." }); + Service.Get().AddHandler("/coreplug", new(this.OnCommand) { HelpMessage = "Access the plugin." }); log.Information("CorePlugin ctor!"); } @@ -81,9 +79,6 @@ namespace Dalamud.CorePlugin } } - /// - public string Name => "Dalamud.CorePlugin"; - /// /// Gets the plugin interface. /// diff --git a/Dalamud/Plugin/IDalamudPlugin.cs b/Dalamud/Plugin/IDalamudPlugin.cs index c752df3d6..b48d55d1c 100644 --- a/Dalamud/Plugin/IDalamudPlugin.cs +++ b/Dalamud/Plugin/IDalamudPlugin.cs @@ -7,8 +7,4 @@ namespace Dalamud.Plugin; /// public interface IDalamudPlugin : IDisposable { - /// - /// Gets the name of the plugin. - /// - string Name { get; } } diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index f7306b5a7..80d6edfd3 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -505,13 +505,6 @@ internal class LocalPlugin : IDisposable return; } - // In-case the manifest name was a placeholder. Can occur when no manifest was included. - if (this.manifest.Name.IsNullOrEmpty() && !this.IsDev) - { - this.manifest.Name = this.instance.Name; - this.manifest.Save(this.manifestFile, "manifest name null or empty"); - } - this.State = PluginState.Loaded; Log.Information($"Finished loading {this.DllFile.Name}"); } From 2119d08926548591eeb80dacec7011235a0a723c Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 11:18:20 +0200 Subject: [PATCH 088/120] fix warnings --- .../Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs | 1 + Dalamud/Logging/PluginLog.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs index afebeaedb..1d6aab1bd 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Widgets/ThirdRepoSettingsEntry.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using System.Threading.Tasks; + using CheapLoc; using Dalamud.Configuration; using Dalamud.Configuration.Internal; diff --git a/Dalamud/Logging/PluginLog.cs b/Dalamud/Logging/PluginLog.cs index c3fe0c808..decf10b4c 100644 --- a/Dalamud/Logging/PluginLog.cs +++ b/Dalamud/Logging/PluginLog.cs @@ -1,4 +1,5 @@ using System.Reflection; + using Dalamud.Plugin.Services; using Serilog; using Serilog.Events; From 6fbcd0e0e4d7715494d4c2d319524a3362682d45 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 13:05:19 +0200 Subject: [PATCH 089/120] chore: don't use ImGuiScene.TextureWrap for any external API, IDalamudTextureWrap does not inherit from ImGuiScene.TextureWrap any longer --- .../AddonArgTypes/AddonRefreshArgs.cs | 1 - Dalamud/Interface/ColorHelpers.cs | 2 +- .../Interface/Internal/DalamudInterface.cs | 4 +- .../Interface/Internal/DalamudTextureWrap.cs | 20 ++++-- .../Interface/Internal/InterfaceManager.cs | 6 +- Dalamud/Interface/Internal/TextureManager.cs | 6 +- .../Internal/Windows/ChangelogWindow.cs | 2 +- .../Windows/Data/Widgets/TexWidget.cs | 4 +- .../Internal/Windows/PluginImageCache.cs | 66 +++++++++---------- .../PluginInstaller/PluginInstallerWindow.cs | 10 +-- .../Windows/Settings/Tabs/SettingsTabAbout.cs | 2 +- .../Internal/Windows/TitleScreenMenuWindow.cs | 2 +- .../TitleScreenMenu/TitleScreenMenu.cs | 13 ++-- .../TitleScreenMenu/TitleScreenMenuEntry.cs | 6 +- Dalamud/Interface/UiBuilder.cs | 12 ++-- Dalamud/Interface/UldWrapper.cs | 8 +-- Dalamud/Plugin/Services/ITitleScreenMenu.cs | 5 +- 17 files changed, 91 insertions(+), 78 deletions(-) diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs b/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs index 60ccaf8ea..6376c16b0 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs +++ b/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs @@ -1,4 +1,3 @@ -using System; using FFXIVClientStructs.FFXIV.Component.GUI; namespace Dalamud.Game.Addon; diff --git a/Dalamud/Interface/ColorHelpers.cs b/Dalamud/Interface/ColorHelpers.cs index dd9ab08f7..b2b489004 100644 --- a/Dalamud/Interface/ColorHelpers.cs +++ b/Dalamud/Interface/ColorHelpers.cs @@ -270,7 +270,7 @@ public static class ColorHelpers => RgbaVector4ToUint(Fade(RgbaUintToVector4(color), amount)); /// - /// Convert a KnownColor to a RGBA vector with values between 0.0f and 1.0f + /// Convert a KnownColor to a RGBA vector with values between 0.0f and 1.0f. /// /// Known Color to convert. /// RGBA Vector with values between 0.0f and 1.0f. diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index 4de73adc7..cfaae485a 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -66,8 +66,8 @@ internal class DalamudInterface : IDisposable, IServiceType private readonly BranchSwitcherWindow branchSwitcherWindow; private readonly HitchSettingsWindow hitchSettingsWindow; - private readonly TextureWrap logoTexture; - private readonly TextureWrap tsmLogoTexture; + private readonly IDalamudTextureWrap logoTexture; + private readonly IDalamudTextureWrap tsmLogoTexture; private bool isCreditsDarkening = false; private OutCubic creditsDarkeningAnimation = new(TimeSpan.FromSeconds(10)); diff --git a/Dalamud/Interface/Internal/DalamudTextureWrap.cs b/Dalamud/Interface/Internal/DalamudTextureWrap.cs index 039873f1f..036686c29 100644 --- a/Dalamud/Interface/Internal/DalamudTextureWrap.cs +++ b/Dalamud/Interface/Internal/DalamudTextureWrap.cs @@ -1,6 +1,4 @@ -using System; - -using ImGuiScene; +using ImGuiScene; namespace Dalamud.Interface.Internal; @@ -8,8 +6,22 @@ namespace Dalamud.Interface.Internal; /// Base TextureWrap interface for all Dalamud-owned texture wraps. /// Used to avoid referencing ImGuiScene. /// -public interface IDalamudTextureWrap : TextureWrap +public interface IDalamudTextureWrap : IDisposable { + /// + /// Gets a texture handle suitable for direct use with ImGui functions. + /// + IntPtr ImGuiHandle { get; } + + /// + /// Gets the width of the texture. + /// + int Width { get; } + + /// + /// Gets the height of the texture. + /// + int Height { get; } } /// diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 6a3256a7f..be6ca3528 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -241,7 +241,7 @@ internal class InterfaceManager : IDisposable, IServiceType /// /// The filepath to load. /// A texture, ready to use in ImGui. - public TextureWrap? LoadImage(string filePath) + public IDalamudTextureWrap? LoadImage(string filePath) { if (this.scene == null) throw new InvalidOperationException("Scene isn't ready."); @@ -264,7 +264,7 @@ internal class InterfaceManager : IDisposable, IServiceType /// /// The data to load. /// A texture, ready to use in ImGui. - public TextureWrap? LoadImage(byte[] imageData) + public IDalamudTextureWrap? LoadImage(byte[] imageData) { if (this.scene == null) throw new InvalidOperationException("Scene isn't ready."); @@ -290,7 +290,7 @@ internal class InterfaceManager : IDisposable, IServiceType /// The height in pixels. /// The number of channels. /// A texture, ready to use in ImGui. - public TextureWrap? LoadImageRaw(byte[] imageData, int width, int height, int numChannels) + public IDalamudTextureWrap? LoadImageRaw(byte[] imageData, int width, int height, int numChannels) { if (this.scene == null) throw new InvalidOperationException("Scene isn't ready."); diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 78af0ebb7..ce08e6cc7 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -43,7 +43,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP private readonly Dictionary activeTextures = new(); - private TextureWrap? fallbackTextureWrap; + private IDalamudTextureWrap? fallbackTextureWrap; /// /// Initializes a new instance of the class. @@ -319,7 +319,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP // Substitute the path here for loading, instead of when getting the respective TextureInfo path = this.GetSubstitutedPath(path); - TextureWrap? wrap; + IDalamudTextureWrap? wrap; try { // We want to load this from the disk, probably, if the path has a root @@ -495,7 +495,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP /// /// Gets or sets the actual texture wrap. May be unpopulated. /// - public TextureWrap? Wrap { get; set; } + public IDalamudTextureWrap? Wrap { get; set; } /// /// Gets or sets the time the texture was last accessed. diff --git a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs index e61cb400b..61010ce0c 100644 --- a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs @@ -36,7 +36,7 @@ Thanks and have fun!"; private readonly string assemblyVersion = Util.AssemblyVersion; - private readonly TextureWrap logoTexture; + private readonly IDalamudTextureWrap logoTexture; /// /// Initializes a new instance of the class. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs index 9f7f69ca2..0cbc401e7 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs @@ -15,7 +15,7 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// internal class TexWidget : IDataWindowWidget { - private readonly List addedTextures = new(); + private readonly List addedTextures = new(); private string iconId = "18"; private bool hiRes = true; @@ -104,7 +104,7 @@ internal class TexWidget : IDataWindowWidget ImGuiHelpers.ScaledDummy(10); - TextureWrap? toRemove = null; + IDalamudTextureWrap? toRemove = null; for (var i = 0; i < this.addedTextures.Count; i++) { if (ImGui.CollapsingHeader($"Tex #{i}")) diff --git a/Dalamud/Interface/Internal/Windows/PluginImageCache.cs b/Dalamud/Interface/Internal/Windows/PluginImageCache.cs index 766f80b23..c334cd4bd 100644 --- a/Dalamud/Interface/Internal/Windows/PluginImageCache.cs +++ b/Dalamud/Interface/Internal/Windows/PluginImageCache.cs @@ -59,24 +59,24 @@ internal class PluginImageCache : IDisposable, IServiceType private readonly Task downloadTask; private readonly Task loadTask; - private readonly ConcurrentDictionary pluginIconMap = new(); - private readonly ConcurrentDictionary pluginImagesMap = new(); + private readonly ConcurrentDictionary pluginIconMap = new(); + private readonly ConcurrentDictionary pluginImagesMap = new(); - private readonly Task emptyTextureTask; - private readonly Task disabledIconTask; - private readonly Task outdatedInstallableIconTask; - private readonly Task defaultIconTask; - private readonly Task troubleIconTask; - private readonly Task updateIconTask; - private readonly Task installedIconTask; - private readonly Task thirdIconTask; - private readonly Task thirdInstalledIconTask; - private readonly Task corePluginIconTask; + private readonly Task emptyTextureTask; + private readonly Task disabledIconTask; + private readonly Task outdatedInstallableIconTask; + private readonly Task defaultIconTask; + private readonly Task troubleIconTask; + private readonly Task updateIconTask; + private readonly Task installedIconTask; + private readonly Task thirdIconTask; + private readonly Task thirdInstalledIconTask; + private readonly Task corePluginIconTask; [ServiceManager.ServiceConstructor] private PluginImageCache(Dalamud dalamud) { - Task? TaskWrapIfNonNull(TextureWrap? tw) => tw == null ? null : Task.FromResult(tw!); + Task? TaskWrapIfNonNull(IDalamudTextureWrap? tw) => tw == null ? null : Task.FromResult(tw!); var imwst = Task.Run(() => this.imWithScene); this.emptyTextureTask = imwst.ContinueWith(task => task.Result.Manager.LoadImageRaw(new byte[64], 8, 8, 4)!); @@ -99,70 +99,70 @@ internal class PluginImageCache : IDisposable, IServiceType /// /// Gets the fallback empty texture. /// - public TextureWrap EmptyTexture => this.emptyTextureTask.IsCompleted - ? this.emptyTextureTask.Result - : this.emptyTextureTask.GetAwaiter().GetResult(); + public IDalamudTextureWrap EmptyTexture => this.emptyTextureTask.IsCompleted + ? this.emptyTextureTask.Result + : this.emptyTextureTask.GetAwaiter().GetResult(); /// /// Gets the disabled plugin icon. /// - public TextureWrap DisabledIcon => this.disabledIconTask.IsCompleted + public IDalamudTextureWrap DisabledIcon => this.disabledIconTask.IsCompleted ? this.disabledIconTask.Result : this.disabledIconTask.GetAwaiter().GetResult(); /// /// Gets the outdated installable plugin icon. /// - public TextureWrap OutdatedInstallableIcon => this.outdatedInstallableIconTask.IsCompleted + public IDalamudTextureWrap OutdatedInstallableIcon => this.outdatedInstallableIconTask.IsCompleted ? this.outdatedInstallableIconTask.Result : this.outdatedInstallableIconTask.GetAwaiter().GetResult(); /// /// Gets the default plugin icon. /// - public TextureWrap DefaultIcon => this.defaultIconTask.IsCompleted + public IDalamudTextureWrap DefaultIcon => this.defaultIconTask.IsCompleted ? this.defaultIconTask.Result : this.defaultIconTask.GetAwaiter().GetResult(); /// /// Gets the plugin trouble icon overlay. /// - public TextureWrap TroubleIcon => this.troubleIconTask.IsCompleted + public IDalamudTextureWrap TroubleIcon => this.troubleIconTask.IsCompleted ? this.troubleIconTask.Result : this.troubleIconTask.GetAwaiter().GetResult(); /// /// Gets the plugin update icon overlay. /// - public TextureWrap UpdateIcon => this.updateIconTask.IsCompleted + public IDalamudTextureWrap UpdateIcon => this.updateIconTask.IsCompleted ? this.updateIconTask.Result : this.updateIconTask.GetAwaiter().GetResult(); /// /// Gets the plugin installed icon overlay. /// - public TextureWrap InstalledIcon => this.installedIconTask.IsCompleted + public IDalamudTextureWrap InstalledIcon => this.installedIconTask.IsCompleted ? this.installedIconTask.Result : this.installedIconTask.GetAwaiter().GetResult(); /// /// Gets the third party plugin icon overlay. /// - public TextureWrap ThirdIcon => this.thirdIconTask.IsCompleted + public IDalamudTextureWrap ThirdIcon => this.thirdIconTask.IsCompleted ? this.thirdIconTask.Result : this.thirdIconTask.GetAwaiter().GetResult(); /// /// Gets the installed third party plugin icon overlay. /// - public TextureWrap ThirdInstalledIcon => this.thirdInstalledIconTask.IsCompleted + public IDalamudTextureWrap ThirdInstalledIcon => this.thirdInstalledIconTask.IsCompleted ? this.thirdInstalledIconTask.Result : this.thirdInstalledIconTask.GetAwaiter().GetResult(); /// /// Gets the core plugin icon. /// - public TextureWrap CorePluginIcon => this.corePluginIconTask.IsCompleted + public IDalamudTextureWrap CorePluginIcon => this.corePluginIconTask.IsCompleted ? this.corePluginIconTask.Result : this.corePluginIconTask.GetAwaiter().GetResult(); @@ -233,7 +233,7 @@ internal class PluginImageCache : IDisposable, IServiceType /// If the plugin was third party sourced. /// Cached image textures, or an empty array. /// True if an entry exists, may be null if currently downloading. - public bool TryGetIcon(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, out TextureWrap? iconTexture) + public bool TryGetIcon(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, out IDalamudTextureWrap? iconTexture) { iconTexture = null; @@ -275,16 +275,16 @@ internal class PluginImageCache : IDisposable, IServiceType /// If the plugin was third party sourced. /// Cached image textures, or an empty array. /// True if the image array exists, may be empty if currently downloading. - public bool TryGetImages(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, out TextureWrap?[] imageTextures) + public bool TryGetImages(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, out IDalamudTextureWrap?[] imageTextures) { if (!this.pluginImagesMap.TryAdd(manifest.InternalName, null)) { var found = this.pluginImagesMap[manifest.InternalName]; - imageTextures = found ?? Array.Empty(); + imageTextures = found ?? Array.Empty(); return true; } - var target = new TextureWrap?[5]; + var target = new IDalamudTextureWrap?[5]; this.pluginImagesMap[manifest.InternalName] = target; imageTextures = target; @@ -304,7 +304,7 @@ internal class PluginImageCache : IDisposable, IServiceType return false; } - private async Task TryLoadImage( + private async Task TryLoadImage( byte[]? bytes, string name, string? loc, @@ -319,7 +319,7 @@ internal class PluginImageCache : IDisposable, IServiceType var interfaceManager = this.imWithScene.Manager; var framework = await Service.GetAsync(); - TextureWrap? image; + IDalamudTextureWrap? image; // FIXME(goat): This is a hack around this call failing randomly in certain situations. Might be related to not being called on the main thread. try { @@ -492,7 +492,7 @@ internal class PluginImageCache : IDisposable, IServiceType Log.Debug("Plugin image loader has shutdown"); } - private async Task DownloadPluginIconAsync(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, ulong requestedFrame) + private async Task DownloadPluginIconAsync(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, ulong requestedFrame) { if (plugin is { IsDev: true }) { @@ -559,7 +559,7 @@ internal class PluginImageCache : IDisposable, IServiceType return icon; } - private async Task DownloadPluginImagesAsync(TextureWrap?[] pluginImages, LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, ulong requestedFrame) + private async Task DownloadPluginImagesAsync(IDalamudTextureWrap?[] pluginImages, LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, ulong requestedFrame) { if (plugin is { IsDev: true }) { diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index dcbdced28..6e2ad862c 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -62,8 +62,8 @@ internal class PluginInstallerWindow : Window, IDisposable private string[] testerImagePaths = new string[5]; private string testerIconPath = string.Empty; - private TextureWrap?[] testerImages; - private TextureWrap? testerIcon; + private IDalamudTextureWrap?[] testerImages; + private IDalamudTextureWrap? testerIcon; private bool testerError = false; private bool testerUpdateAvailable = false; @@ -1525,7 +1525,7 @@ internal class PluginInstallerWindow : Window, IDisposable ImGuiHelpers.ScaledDummy(20); - static void CheckImageSize(TextureWrap? image, int maxWidth, int maxHeight, bool requireSquare) + static void CheckImageSize(IDalamudTextureWrap? image, int maxWidth, int maxHeight, bool requireSquare) { if (image == null) return; @@ -1570,7 +1570,7 @@ internal class PluginInstallerWindow : Window, IDisposable this.testerIcon = im.LoadImage(this.testerIconPath); } - this.testerImages = new TextureWrap[this.testerImagePaths.Length]; + this.testerImages = new IDalamudTextureWrap[this.testerImagePaths.Length]; for (var i = 0; i < this.testerImagePaths.Length; i++) { @@ -1822,7 +1822,7 @@ internal class PluginInstallerWindow : Window, IDisposable var rectOffset = ImGui.GetWindowContentRegionMin() + ImGui.GetWindowPos(); if (ImGui.IsRectVisible(rectOffset + cursorBeforeImage, rectOffset + cursorBeforeImage + iconSize)) { - TextureWrap icon; + IDalamudTextureWrap icon; if (log is PluginChangelogEntry pluginLog) { icon = this.imageCache.DefaultIcon; diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs index 9a7236f2f..ec9833b78 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs @@ -171,7 +171,7 @@ Dalamud is licensed under AGPL v3 or later. Contribute at: https://github.com/goatcorp/Dalamud "; - private readonly TextureWrap logoTexture; + private readonly IDalamudTextureWrap logoTexture; private readonly Stopwatch creditsThrottler; private string creditsText; diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 20d260704..e77a3db4e 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -25,7 +25,7 @@ internal class TitleScreenMenuWindow : Window, IDisposable private const float TargetFontSizePt = 18f; private const float TargetFontSizePx = TargetFontSizePt * 4 / 3; - private readonly TextureWrap shadeTexture; + private readonly IDalamudTextureWrap shadeTexture; private readonly Dictionary shadeEasings = new(); private readonly Dictionary moveEasings = new(); diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs index 3123ffbb8..6665bbafb 100644 --- a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Reflection; +using Dalamud.Interface.Internal; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; @@ -32,7 +33,7 @@ internal class TitleScreenMenu : IServiceType, ITitleScreenMenu public IReadOnlyList Entries => this.entries; /// - public TitleScreenMenuEntry AddEntry(string text, TextureWrap texture, Action onTriggered) + public TitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered) { if (texture.Height != TextureSize || texture.Width != TextureSize) { @@ -55,7 +56,7 @@ internal class TitleScreenMenu : IServiceType, ITitleScreenMenu } /// - public TitleScreenMenuEntry AddEntry(ulong priority, string text, TextureWrap texture, Action onTriggered) + public TitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) { if (texture.Height != TextureSize || texture.Width != TextureSize) { @@ -91,7 +92,7 @@ internal class TitleScreenMenu : IServiceType, ITitleScreenMenu /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - internal TitleScreenMenuEntry AddEntryCore(ulong priority, string text, TextureWrap texture, Action onTriggered) + internal TitleScreenMenuEntry AddEntryCore(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) { if (texture.Height != TextureSize || texture.Width != TextureSize) { @@ -117,7 +118,7 @@ internal class TitleScreenMenu : IServiceType, ITitleScreenMenu /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - internal TitleScreenMenuEntry AddEntryCore(string text, TextureWrap texture, Action onTriggered) + internal TitleScreenMenuEntry AddEntryCore(string text, IDalamudTextureWrap texture, Action onTriggered) { if (texture.Height != TextureSize || texture.Width != TextureSize) { @@ -169,7 +170,7 @@ internal class TitleScreenMenuPluginScoped : IDisposable, IServiceType, ITitleSc } /// - public TitleScreenMenuEntry AddEntry(string text, TextureWrap texture, Action onTriggered) + public TitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered) { var entry = this.titleScreenMenuService.AddEntry(text, texture, onTriggered); this.pluginEntries.Add(entry); @@ -178,7 +179,7 @@ internal class TitleScreenMenuPluginScoped : IDisposable, IServiceType, ITitleSc } /// - public TitleScreenMenuEntry AddEntry(ulong priority, string text, TextureWrap texture, Action onTriggered) + public TitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) { var entry = this.titleScreenMenuService.AddEntry(priority, text, texture, onTriggered); this.pluginEntries.Add(entry); diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs index 18acc4f47..76382ace2 100644 --- a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs @@ -1,6 +1,6 @@ using System.Reflection; -using ImGuiScene; +using Dalamud.Interface.Internal; namespace Dalamud.Interface; @@ -19,7 +19,7 @@ public class TitleScreenMenuEntry : IComparable /// The text to show. /// The texture to show. /// The action to execute when the option is selected. - internal TitleScreenMenuEntry(Assembly? callingAssembly, ulong priority, string text, TextureWrap texture, Action onTriggered) + internal TitleScreenMenuEntry(Assembly? callingAssembly, ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) { this.CallingAssembly = callingAssembly; this.Priority = priority; @@ -41,7 +41,7 @@ public class TitleScreenMenuEntry : IComparable /// /// Gets or sets the texture of this entry. /// - public TextureWrap Texture { get; set; } + public IDalamudTextureWrap Texture { get; set; } /// /// Gets or sets a value indicating whether or not this entry is internal. diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs index 95ee28f56..dd2e5bad3 100644 --- a/Dalamud/Interface/UiBuilder.cs +++ b/Dalamud/Interface/UiBuilder.cs @@ -235,7 +235,7 @@ public sealed class UiBuilder : IDisposable /// /// The full filepath to the image. /// A object wrapping the created image. Use inside ImGui.Image(). - public TextureWrap LoadImage(string filePath) + public IDalamudTextureWrap LoadImage(string filePath) => this.InterfaceManagerWithScene?.LoadImage(filePath) ?? throw new InvalidOperationException("Load failed."); @@ -244,7 +244,7 @@ public sealed class UiBuilder : IDisposable /// /// A byte array containing the raw image data. /// A object wrapping the created image. Use inside ImGui.Image(). - public TextureWrap LoadImage(byte[] imageData) + public IDalamudTextureWrap LoadImage(byte[] imageData) => this.InterfaceManagerWithScene?.LoadImage(imageData) ?? throw new InvalidOperationException("Load failed."); @@ -256,7 +256,7 @@ public sealed class UiBuilder : IDisposable /// The height of the image contained in . /// The number of channels (bytes per pixel) of the image contained in . This should usually be 4. /// A object wrapping the created image. Use inside ImGui.Image(). - public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) + public IDalamudTextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) => this.InterfaceManagerWithScene?.LoadImageRaw(imageData, width, height, numChannels) ?? throw new InvalidOperationException("Load failed."); @@ -273,7 +273,7 @@ public sealed class UiBuilder : IDisposable /// /// The full filepath to the image. /// A object wrapping the created image. Use inside ImGui.Image(). - public Task LoadImageAsync(string filePath) => Task.Run( + public Task LoadImageAsync(string filePath) => Task.Run( async () => (await this.InterfaceManagerWithSceneAsync).LoadImage(filePath) ?? throw new InvalidOperationException("Load failed.")); @@ -283,7 +283,7 @@ public sealed class UiBuilder : IDisposable /// /// A byte array containing the raw image data. /// A object wrapping the created image. Use inside ImGui.Image(). - public Task LoadImageAsync(byte[] imageData) => Task.Run( + public Task LoadImageAsync(byte[] imageData) => Task.Run( async () => (await this.InterfaceManagerWithSceneAsync).LoadImage(imageData) ?? throw new InvalidOperationException("Load failed.")); @@ -296,7 +296,7 @@ public sealed class UiBuilder : IDisposable /// The height of the image contained in . /// The number of channels (bytes per pixel) of the image contained in . This should usually be 4. /// A object wrapping the created image. Use inside ImGui.Image(). - public Task LoadImageRawAsync(byte[] imageData, int width, int height, int numChannels) => Task.Run( + public Task LoadImageRawAsync(byte[] imageData, int width, int height, int numChannels) => Task.Run( async () => (await this.InterfaceManagerWithSceneAsync).LoadImageRaw(imageData, width, height, numChannels) ?? throw new InvalidOperationException("Load failed.")); diff --git a/Dalamud/Interface/UldWrapper.cs b/Dalamud/Interface/UldWrapper.cs index d41256fa2..e78546ed9 100644 --- a/Dalamud/Interface/UldWrapper.cs +++ b/Dalamud/Interface/UldWrapper.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Generic; using System.Linq; using Dalamud.Data; +using Dalamud.Interface.Internal; using Dalamud.Utility; using ImGuiScene; using Lumina.Data.Files; @@ -38,7 +38,7 @@ public class UldWrapper : IDisposable /// The path of the requested texture. /// The index of the desired icon. /// A TextureWrap containing the requested part if it exists and null otherwise. - public TextureWrap? LoadTexturePart(string texturePath, int part) + public IDalamudTextureWrap? LoadTexturePart(string texturePath, int part) { if (!this.Valid) { @@ -67,7 +67,7 @@ public class UldWrapper : IDisposable this.Uld = null; } - private TextureWrap? CreateTexture(uint id, int width, int height, bool hd, byte[] rgbaData, int partIdx) + private IDalamudTextureWrap? CreateTexture(uint id, int width, int height, bool hd, byte[] rgbaData, int partIdx) { var idx = 0; UldRoot.PartData? partData = null; @@ -105,7 +105,7 @@ public class UldWrapper : IDisposable return this.CopyRect(width, height, rgbaData, d); } - private TextureWrap? CopyRect(int width, int height, byte[] rgbaData, UldRoot.PartData part) + private IDalamudTextureWrap? CopyRect(int width, int height, byte[] rgbaData, UldRoot.PartData part) { if (part.V + part.W > width || part.U + part.H > height) { diff --git a/Dalamud/Plugin/Services/ITitleScreenMenu.cs b/Dalamud/Plugin/Services/ITitleScreenMenu.cs index 2094dc435..b4af06e71 100644 --- a/Dalamud/Plugin/Services/ITitleScreenMenu.cs +++ b/Dalamud/Plugin/Services/ITitleScreenMenu.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Dalamud.Interface; +using Dalamud.Interface.Internal; using ImGuiScene; namespace Dalamud.Plugin.Services; @@ -23,7 +24,7 @@ public interface ITitleScreenMenu /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - public TitleScreenMenuEntry AddEntry(string text, TextureWrap texture, Action onTriggered); + public TitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered); /// /// Adds a new entry to the title screen menu. @@ -34,7 +35,7 @@ public interface ITitleScreenMenu /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - public TitleScreenMenuEntry AddEntry(ulong priority, string text, TextureWrap texture, Action onTriggered); + public TitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered); /// /// Remove an entry from the title screen menu. From c767971a364fae3e3a724abf21bfad07f1366488 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 13:09:43 +0200 Subject: [PATCH 090/120] move around new Addon services a bit to match folder structure --- Dalamud/Dalamud.csproj | 4 ++++ .../{AddonEventManager => Addon/Events}/AddonCursorType.cs | 2 +- .../{AddonEventManager => Addon/Events}/AddonEventEntry.cs | 6 ++---- .../Events}/AddonEventHandle.cs | 4 +--- .../Events}/AddonEventListener.cs | 3 +-- .../Events}/AddonEventManager.cs | 7 ++++--- .../Events}/AddonEventManagerAddressResolver.cs | 2 +- .../{AddonEventManager => Addon/Events}/AddonEventType.cs | 2 +- .../Events}/IAddonEventHandle.cs | 4 +--- .../Events}/PluginEventController.cs | 5 ++--- .../Lifecycle}/AddonArgTypes/AddonArgs.cs | 2 +- .../Lifecycle}/AddonArgTypes/AddonDrawArgs.cs | 2 +- .../Lifecycle}/AddonArgTypes/AddonFinalizeArgs.cs | 2 +- .../Lifecycle}/AddonArgTypes/AddonRefreshArgs.cs | 2 +- .../Lifecycle}/AddonArgTypes/AddonRequestedUpdateArgs.cs | 2 +- .../Lifecycle}/AddonArgTypes/AddonSetupArgs.cs | 6 ++---- .../Lifecycle}/AddonArgTypes/AddonUpdateArgs.cs | 2 +- .../{AddonLifecycle => Addon/Lifecycle}/AddonArgsType.cs | 2 +- .../Game/{AddonLifecycle => Addon/Lifecycle}/AddonEvent.cs | 2 +- .../{AddonLifecycle => Addon/Lifecycle}/AddonLifecycle.cs | 4 ++-- .../Lifecycle}/AddonLifecycleAddressResolver.cs | 2 +- .../Lifecycle}/AddonLifecycleEventListener.cs | 2 +- Dalamud/Game/Gui/Dtr/DtrBar.cs | 3 +++ .../Windows/SelfTest/AgingSteps/AddonLifecycleAgingStep.cs | 2 ++ Dalamud/Plugin/Services/IAddonEventManager.cs | 1 + Dalamud/Plugin/Services/IAddonLifecycle.cs | 2 ++ 26 files changed, 40 insertions(+), 37 deletions(-) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonCursorType.cs (97%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonEventEntry.cs (96%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonEventHandle.cs (90%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonEventListener.cs (98%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonEventManager.cs (98%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonEventManagerAddressResolver.cs (94%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/AddonEventType.cs (98%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/IAddonEventHandle.cs (93%) rename Dalamud/Game/{AddonEventManager => Addon/Events}/PluginEventController.cs (98%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonArgs.cs (96%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonDrawArgs.cs (77%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonFinalizeArgs.cs (79%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonRefreshArgs.cs (92%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonRequestedUpdateArgs.cs (89%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonSetupArgs.cs (86%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgTypes/AddonUpdateArgs.cs (86%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonArgsType.cs (94%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonEvent.cs (97%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonLifecycle.cs (99%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonLifecycleAddressResolver.cs (97%) rename Dalamud/Game/{AddonLifecycle => Addon/Lifecycle}/AddonLifecycleEventListener.cs (97%) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index dd84c42e5..5093fbfe9 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -105,6 +105,10 @@ + + + + diff --git a/Dalamud/Game/AddonEventManager/AddonCursorType.cs b/Dalamud/Game/Addon/Events/AddonCursorType.cs similarity index 97% rename from Dalamud/Game/AddonEventManager/AddonCursorType.cs rename to Dalamud/Game/Addon/Events/AddonCursorType.cs index 57d58c60c..83a81582c 100644 --- a/Dalamud/Game/AddonEventManager/AddonCursorType.cs +++ b/Dalamud/Game/Addon/Events/AddonCursorType.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Reimplementation of CursorType. diff --git a/Dalamud/Game/AddonEventManager/AddonEventEntry.cs b/Dalamud/Game/Addon/Events/AddonEventEntry.cs similarity index 96% rename from Dalamud/Game/AddonEventManager/AddonEventEntry.cs rename to Dalamud/Game/Addon/Events/AddonEventEntry.cs index 48c3feb24..a7430acf0 100644 --- a/Dalamud/Game/AddonEventManager/AddonEventEntry.cs +++ b/Dalamud/Game/Addon/Events/AddonEventEntry.cs @@ -1,10 +1,8 @@ -using System; - -using Dalamud.Memory; +using Dalamud.Memory; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// This class represents a registered event that a plugin registers with a native ui node. diff --git a/Dalamud/Game/AddonEventManager/AddonEventHandle.cs b/Dalamud/Game/Addon/Events/AddonEventHandle.cs similarity index 90% rename from Dalamud/Game/AddonEventManager/AddonEventHandle.cs rename to Dalamud/Game/Addon/Events/AddonEventHandle.cs index 48abba9a0..fb0e2886c 100644 --- a/Dalamud/Game/AddonEventManager/AddonEventHandle.cs +++ b/Dalamud/Game/Addon/Events/AddonEventHandle.cs @@ -1,6 +1,4 @@ -using System; - -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Class that represents a addon event handle. diff --git a/Dalamud/Game/AddonEventManager/AddonEventListener.cs b/Dalamud/Game/Addon/Events/AddonEventListener.cs similarity index 98% rename from Dalamud/Game/AddonEventManager/AddonEventListener.cs rename to Dalamud/Game/Addon/Events/AddonEventListener.cs index 6f7c55c4c..ceac38108 100644 --- a/Dalamud/Game/AddonEventManager/AddonEventListener.cs +++ b/Dalamud/Game/Addon/Events/AddonEventListener.cs @@ -1,9 +1,8 @@ -using System; using System.Runtime.InteropServices; using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Event listener class for managing custom events. diff --git a/Dalamud/Game/AddonEventManager/AddonEventManager.cs b/Dalamud/Game/Addon/Events/AddonEventManager.cs similarity index 98% rename from Dalamud/Game/AddonEventManager/AddonEventManager.cs rename to Dalamud/Game/Addon/Events/AddonEventManager.cs index dfc037e23..8ec77b10d 100644 --- a/Dalamud/Game/AddonEventManager/AddonEventManager.cs +++ b/Dalamud/Game/Addon/Events/AddonEventManager.cs @@ -1,7 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; @@ -11,7 +12,7 @@ using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Service provider for addon event management. diff --git a/Dalamud/Game/AddonEventManager/AddonEventManagerAddressResolver.cs b/Dalamud/Game/Addon/Events/AddonEventManagerAddressResolver.cs similarity index 94% rename from Dalamud/Game/AddonEventManager/AddonEventManagerAddressResolver.cs rename to Dalamud/Game/Addon/Events/AddonEventManagerAddressResolver.cs index 71a6093bb..1405446fe 100644 --- a/Dalamud/Game/AddonEventManager/AddonEventManagerAddressResolver.cs +++ b/Dalamud/Game/Addon/Events/AddonEventManagerAddressResolver.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// AddonEventManager memory address resolver. diff --git a/Dalamud/Game/AddonEventManager/AddonEventType.cs b/Dalamud/Game/Addon/Events/AddonEventType.cs similarity index 98% rename from Dalamud/Game/AddonEventManager/AddonEventType.cs rename to Dalamud/Game/Addon/Events/AddonEventType.cs index 74f35c257..2c6c96334 100644 --- a/Dalamud/Game/AddonEventManager/AddonEventType.cs +++ b/Dalamud/Game/Addon/Events/AddonEventType.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Reimplementation of AtkEventType. diff --git a/Dalamud/Game/AddonEventManager/IAddonEventHandle.cs b/Dalamud/Game/Addon/Events/IAddonEventHandle.cs similarity index 93% rename from Dalamud/Game/AddonEventManager/IAddonEventHandle.cs rename to Dalamud/Game/Addon/Events/IAddonEventHandle.cs index 3b2c5c3ae..f9272c92a 100644 --- a/Dalamud/Game/AddonEventManager/IAddonEventHandle.cs +++ b/Dalamud/Game/Addon/Events/IAddonEventHandle.cs @@ -1,6 +1,4 @@ -using System; - -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Interface representing the data used for managing AddonEvents. diff --git a/Dalamud/Game/AddonEventManager/PluginEventController.cs b/Dalamud/Game/Addon/Events/PluginEventController.cs similarity index 98% rename from Dalamud/Game/AddonEventManager/PluginEventController.cs rename to Dalamud/Game/Addon/Events/PluginEventController.cs index b66bbc99e..7847dd482 100644 --- a/Dalamud/Game/AddonEventManager/PluginEventController.cs +++ b/Dalamud/Game/Addon/Events/PluginEventController.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Dalamud.Game.Gui; @@ -8,7 +7,7 @@ using Dalamud.Memory; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Events; /// /// Class to manage creating and cleaning up events per-plugin. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs similarity index 96% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs index 949d3fde9..334542c71 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonArgs.cs @@ -1,7 +1,7 @@ using Dalamud.Memory; using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Base class for AddonLifecycle AddonArgTypes. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonDrawArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonDrawArgs.cs similarity index 77% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonDrawArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonDrawArgs.cs index d93001d1c..6bb72f567 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonDrawArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonDrawArgs.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Addon argument data for Finalize events. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonFinalizeArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFinalizeArgs.cs similarity index 79% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonFinalizeArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFinalizeArgs.cs index ed7aa1b3c..782943955 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonFinalizeArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFinalizeArgs.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Addon argument data for Finalize events. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonRefreshArgs.cs similarity index 92% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonRefreshArgs.cs index 6376c16b0..a50dc68f6 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRefreshArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonRefreshArgs.cs @@ -1,6 +1,6 @@ using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Addon argument data for Finalize events. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRequestedUpdateArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonRequestedUpdateArgs.cs similarity index 89% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRequestedUpdateArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonRequestedUpdateArgs.cs index a31369aaf..e73d11e23 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonRequestedUpdateArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonRequestedUpdateArgs.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Addon argument data for Finalize events. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonSetupArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonSetupArgs.cs similarity index 86% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonSetupArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonSetupArgs.cs index 17c87967a..df2ec26be 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonSetupArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonSetupArgs.cs @@ -1,8 +1,6 @@ -using System; +using FFXIVClientStructs.FFXIV.Component.GUI; -using FFXIVClientStructs.FFXIV.Component.GUI; - -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Addon argument data for Setup events. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonUpdateArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonUpdateArgs.cs similarity index 86% rename from Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonUpdateArgs.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonUpdateArgs.cs index 993883d77..6870746db 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonUpdateArgs.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonUpdateArgs.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes; /// /// Addon argument data for Finalize events. diff --git a/Dalamud/Game/AddonLifecycle/AddonArgsType.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs similarity index 94% rename from Dalamud/Game/AddonLifecycle/AddonArgsType.cs rename to Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs index 8a07d445b..11f73a4de 100644 --- a/Dalamud/Game/AddonLifecycle/AddonArgsType.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle; /// /// Enumeration for available AddonLifecycle arg data. diff --git a/Dalamud/Game/AddonLifecycle/AddonEvent.cs b/Dalamud/Game/Addon/Lifecycle/AddonEvent.cs similarity index 97% rename from Dalamud/Game/AddonLifecycle/AddonEvent.cs rename to Dalamud/Game/Addon/Lifecycle/AddonEvent.cs index cfc83fb8a..75a77482d 100644 --- a/Dalamud/Game/AddonLifecycle/AddonEvent.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonEvent.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle; /// /// Enumeration for available AddonLifecycle events. diff --git a/Dalamud/Game/AddonLifecycle/AddonLifecycle.cs b/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs similarity index 99% rename from Dalamud/Game/AddonLifecycle/AddonLifecycle.cs rename to Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs index 8de98abcc..f1ee69f2b 100644 --- a/Dalamud/Game/AddonLifecycle/AddonLifecycle.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Hooking; using Dalamud.Hooking.Internal; using Dalamud.IoC; @@ -11,7 +11,7 @@ using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Component.GUI; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle; /// /// This class provides events for in-game addon lifecycles. diff --git a/Dalamud/Game/AddonLifecycle/AddonLifecycleAddressResolver.cs b/Dalamud/Game/Addon/Lifecycle/AddonLifecycleAddressResolver.cs similarity index 97% rename from Dalamud/Game/AddonLifecycle/AddonLifecycleAddressResolver.cs rename to Dalamud/Game/Addon/Lifecycle/AddonLifecycleAddressResolver.cs index 16fd54832..7690db50d 100644 --- a/Dalamud/Game/AddonLifecycle/AddonLifecycleAddressResolver.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonLifecycleAddressResolver.cs @@ -1,4 +1,4 @@ -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle; /// /// AddonLifecycleService memory address resolver. diff --git a/Dalamud/Game/AddonLifecycle/AddonLifecycleEventListener.cs b/Dalamud/Game/Addon/Lifecycle/AddonLifecycleEventListener.cs similarity index 97% rename from Dalamud/Game/AddonLifecycle/AddonLifecycleEventListener.cs rename to Dalamud/Game/Addon/Lifecycle/AddonLifecycleEventListener.cs index 12ccf5e8f..6464a1edd 100644 --- a/Dalamud/Game/AddonLifecycle/AddonLifecycleEventListener.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonLifecycleEventListener.cs @@ -1,6 +1,6 @@ using Dalamud.Plugin.Services; -namespace Dalamud.Game.Addon; +namespace Dalamud.Game.Addon.Lifecycle; /// /// This class is a helper for tracking and invoking listener delegates. diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs index e8e6ca6c5..06d37e7ec 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBar.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs @@ -4,6 +4,9 @@ using System.Linq; using Dalamud.Configuration.Internal; using Dalamud.Game.Addon; +using Dalamud.Game.Addon.Events; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.Text.SeStringHandling; using Dalamud.IoC; using Dalamud.IoC.Internal; diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/AddonLifecycleAgingStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/AddonLifecycleAgingStep.cs index a9948430f..b2229e4e4 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/AddonLifecycleAgingStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/AgingSteps/AddonLifecycleAgingStep.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using Dalamud.Game.Addon; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using ImGuiNET; namespace Dalamud.Interface.Internal.Windows.SelfTest.AgingSteps; diff --git a/Dalamud/Plugin/Services/IAddonEventManager.cs b/Dalamud/Plugin/Services/IAddonEventManager.cs index 52f836b4f..e696bbaae 100644 --- a/Dalamud/Plugin/Services/IAddonEventManager.cs +++ b/Dalamud/Plugin/Services/IAddonEventManager.cs @@ -1,4 +1,5 @@ using Dalamud.Game.Addon; +using Dalamud.Game.Addon.Events; namespace Dalamud.Plugin.Services; diff --git a/Dalamud/Plugin/Services/IAddonLifecycle.cs b/Dalamud/Plugin/Services/IAddonLifecycle.cs index 2bc41a366..6f44349d5 100644 --- a/Dalamud/Plugin/Services/IAddonLifecycle.cs +++ b/Dalamud/Plugin/Services/IAddonLifecycle.cs @@ -2,6 +2,8 @@ using System.Runtime.InteropServices; using Dalamud.Game.Addon; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; namespace Dalamud.Plugin.Services; From 6295f047aec8a54e9ebe20ab4352aa0a18fc4e06 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 23 Sep 2023 07:55:17 -0700 Subject: [PATCH 091/120] Add Size Vector to IDalamudTextureWrap --- Dalamud/Interface/Internal/DalamudTextureWrap.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Dalamud/Interface/Internal/DalamudTextureWrap.cs b/Dalamud/Interface/Internal/DalamudTextureWrap.cs index 036686c29..9737d9f7b 100644 --- a/Dalamud/Interface/Internal/DalamudTextureWrap.cs +++ b/Dalamud/Interface/Internal/DalamudTextureWrap.cs @@ -1,4 +1,6 @@ -using ImGuiScene; +using System.Numerics; + +using ImGuiScene; namespace Dalamud.Interface.Internal; @@ -22,6 +24,11 @@ public interface IDalamudTextureWrap : IDisposable /// Gets the height of the texture. /// int Height { get; } + + /// + /// Gets the size vector of the texture using Width, Height. + /// + Vector2 Size => new(this.Width, this.Height); } /// From 64f76ec69f26383e4a0af9b3567caab954d143ff Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sat, 23 Sep 2023 17:20:19 +0200 Subject: [PATCH 092/120] Fix SignatureHelper Hooks --- Dalamud/Utility/Signatures/SignatureHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index 9186b1fc0..e2c9926a8 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -161,7 +161,7 @@ internal static class SignatureHelper continue; } - var hook = creator.Invoke(null, new object?[] { ptr, detour, IGameInteropProvider.HookBackend.Automatic }) as IDalamudHook; + var hook = creator.Invoke(null, new object?[] { ptr, detour, false }) as IDalamudHook; info.SetValue(self, hook); createdHooks.Add(hook); From 8527e035f11afbd963706232512b18876348700f Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 17:37:41 +0200 Subject: [PATCH 093/120] chore: remove refcounting, keepalive logic from TextureManager, remove scoped service Makes this whole thing a lot simpler to use and easier to understand. --- Dalamud/Interface/Internal/TextureManager.cs | 193 +++---------------- Dalamud/Plugin/Services/ITextureProvider.cs | 6 +- 2 files changed, 25 insertions(+), 174 deletions(-) diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index ce08e6cc7..542299656 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -1,8 +1,6 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Numerics; using Dalamud.Data; @@ -11,13 +9,14 @@ using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; -using ImGuiScene; using Lumina.Data.Files; using Lumina.Data.Parsing.Tex.Buffers; using SharpDX.DXGI; namespace Dalamud.Interface.Internal; +// TODO API10: Remove keepAlive from public APIs + /// /// Service responsible for loading and disposing ImGui texture wraps. /// @@ -25,9 +24,10 @@ namespace Dalamud.Interface.Internal; [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] #pragma warning disable SA1015 +[ResolveVia] [ResolveVia] #pragma warning restore SA1015 -internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionProvider +internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITextureSubstitutionProvider { private const string IconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}.tex"; private const string HighResolutionIconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}_hr1.tex"; @@ -78,16 +78,16 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP /// If null, default to the game's current language. /// /// - /// Prevent Dalamud from automatically unloading this icon to save memory. Usually does not need to be set. + /// Not used. This parameter is ignored. /// /// /// Null, if the icon does not exist in the specified configuration, or a texture wrap that can be used /// to render the icon. /// - public TextureManagerTextureWrap? GetIcon(uint iconId, ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes, ClientLanguage? language = null, bool keepAlive = false) + public IDalamudTextureWrap? GetIcon(uint iconId, ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes, ClientLanguage? language = null, bool keepAlive = false) { var path = this.GetIconPath(iconId, flags, language); - return path == null ? null : this.CreateWrap(path, keepAlive); + return path == null ? null : this.CreateWrap(path); } /// @@ -171,16 +171,16 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP /// You may only specify paths in the game's VFS. /// /// The path to the texture in the game's VFS. - /// Prevent Dalamud from automatically unloading this texture to save memory. Usually does not need to be set. + /// Not used. This parameter is ignored. /// Null, if the icon does not exist, or a texture wrap that can be used to render the texture. - public TextureManagerTextureWrap? GetTextureFromGame(string path, bool keepAlive = false) + public IDalamudTextureWrap? GetTextureFromGame(string path, bool keepAlive = false) { ArgumentException.ThrowIfNullOrEmpty(path); if (Path.IsPathRooted(path)) throw new ArgumentException("Use GetTextureFromFile() to load textures directly from a file.", nameof(path)); - return !this.dataManager.FileExists(path) ? null : this.CreateWrap(path, keepAlive); + return !this.dataManager.FileExists(path) ? null : this.CreateWrap(path); } /// @@ -190,12 +190,12 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP /// This API can load .png and .tex files. /// /// The FileInfo describing the image or texture file. - /// Prevent Dalamud from automatically unloading this texture to save memory. Usually does not need to be set. + /// Not used. This parameter is ignored. /// Null, if the file does not exist, or a texture wrap that can be used to render the texture. - public TextureManagerTextureWrap? GetTextureFromFile(FileInfo file, bool keepAlive = false) + public IDalamudTextureWrap? GetTextureFromFile(FileInfo file, bool keepAlive = false) { ArgumentNullException.ThrowIfNull(file); - return !file.Exists ? null : this.CreateWrap(file.FullName, keepAlive); + return !file.Exists ? null : this.CreateWrap(file.FullName); } /// @@ -307,8 +307,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP throw new Exception("null info in activeTextures"); } - if (info.KeepAliveCount == 0) - info.LastAccess = DateTime.UtcNow; + info.LastAccess = DateTime.UtcNow; if (info is { Wrap: not null }) return info; @@ -384,33 +383,6 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP return info; } - /// - /// Notify the system about an instance of a texture wrap being disposed. - /// If required conditions are met, the texture will be unloaded at the next update. - /// - /// The path to the texture. - /// Whether or not this handle was created in keep-alive mode. - internal void NotifyTextureDisposed(string path, bool keepAlive) - { - lock (this.activeTextures) - { - if (!this.activeTextures.TryGetValue(path, out var info)) - { - Log.Warning("Disposing texture that didn't exist: {Path}", path); - return; - } - - info.RefCount--; - - if (keepAlive) - info.KeepAliveCount--; - - // Clean it up by the next update. If it's re-requested in-between, we don't reload it. - if (info.RefCount <= 0) - info.LastAccess = default; - } - } - private static string FormatIconPath(uint iconId, string? type, bool highResolution) { var format = highResolution ? HighResolutionIconFileFormat : IconFileFormat; @@ -422,23 +394,15 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP return string.Format(format, iconId / 1000, type, iconId); } - private TextureManagerTextureWrap? CreateWrap(string path, bool keepAlive) + private TextureManagerTextureWrap? CreateWrap(string path) { lock (this.activeTextures) { // This will create the texture. // That's fine, it's probably used immediately and this will let the plugin catch load errors. var info = this.GetInfo(path, rethrow: true); - - // We need to increase the refcounts here while locking the collection! - // Otherwise, if this is loaded from a task, cleanup might already try to delete it - // before it can be increased. - info.RefCount++; - - if (keepAlive) - info.KeepAliveCount++; - return new TextureManagerTextureWrap(path, info.Extents, keepAlive, this); + return new TextureManagerTextureWrap(path, info.Extents, this); } } @@ -450,19 +414,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP foreach (var texInfo in this.activeTextures) { - if (texInfo.Value.RefCount == 0) - { - Log.Verbose("Evicting {Path} since no refs", texInfo.Key); - - Debug.Assert(texInfo.Value.KeepAliveCount == 0, "texInfo.Value.KeepAliveCount == 0"); - - texInfo.Value.Wrap?.Dispose(); - texInfo.Value.Wrap = null; - toRemove.Add(texInfo.Key); - continue; - } - - if (texInfo.Value.KeepAliveCount > 0 || texInfo.Value.Wrap == null) + if (texInfo.Value.Wrap == null) continue; if (DateTime.UtcNow - texInfo.Value.LastAccess > TimeSpan.FromMilliseconds(MillisecondsEvictionTime)) @@ -470,6 +422,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP Log.Verbose("Evicting {Path} since too old", texInfo.Key); texInfo.Value.Wrap.Dispose(); texInfo.Value.Wrap = null; + toRemove.Add(texInfo.Key); } } @@ -501,16 +454,6 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP /// Gets or sets the time the texture was last accessed. /// public DateTime LastAccess { get; set; } - - /// - /// Gets or sets the number of active holders of this texture. - /// - public uint RefCount { get; set; } - - /// - /// Gets or sets the number of active holders that want this texture to stay alive forever. - /// - public uint KeepAliveCount { get; set; } /// /// Gets or sets the extents of the texture. @@ -519,90 +462,6 @@ internal class TextureManager : IDisposable, IServiceType, ITextureSubstitutionP } } -/// -/// Plugin-scoped version of a texture manager. -/// -[PluginInterface] -[InterfaceVersion("1.0")] -[ServiceManager.ScopedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -internal class TextureProviderPluginScoped : ITextureProvider, IServiceType, IDisposable -{ - private readonly TextureManager textureManager; - - private readonly ConcurrentBag trackedTextures = new(); - - /// - /// Initializes a new instance of the class. - /// - /// TextureManager instance. - public TextureProviderPluginScoped(TextureManager textureManager) - { - this.textureManager = textureManager; - } - - /// - public IDalamudTextureWrap? GetIcon( - uint iconId, - ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.ItemHighQuality, - ClientLanguage? language = null, - bool keepAlive = false) - { - var wrap = this.textureManager.GetIcon(iconId, flags, language, keepAlive); - if (wrap == null) - return null; - - this.trackedTextures.Add(wrap); - return wrap; - } - - /// - public string? GetIconPath(uint iconId, ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes, ClientLanguage? language = null) - => this.textureManager.GetIconPath(iconId, flags, language); - - /// - public IDalamudTextureWrap? GetTextureFromGame(string path, bool keepAlive = false) - { - ArgumentException.ThrowIfNullOrEmpty(path); - - var wrap = this.textureManager.GetTextureFromGame(path, keepAlive); - if (wrap == null) - return null; - - this.trackedTextures.Add(wrap); - return wrap; - } - - /// - public IDalamudTextureWrap? GetTextureFromFile(FileInfo file, bool keepAlive) - { - ArgumentNullException.ThrowIfNull(file); - - var wrap = this.textureManager.GetTextureFromFile(file, keepAlive); - if (wrap == null) - return null; - - this.trackedTextures.Add(wrap); - return wrap; - } - - /// - public IDalamudTextureWrap? GetTexture(TexFile file) - => this.textureManager.GetTexture(file); - - /// - public void Dispose() - { - // Dispose all leaked textures - foreach (var textureWrap in this.trackedTextures.Where(x => !x.IsDisposed)) - { - textureWrap.Dispose(); - } - } -} - /// /// Wrap. /// @@ -610,19 +469,16 @@ internal class TextureManagerTextureWrap : IDalamudTextureWrap { private readonly TextureManager manager; private readonly string path; - private readonly bool keepAlive; /// /// Initializes a new instance of the class. /// /// The path to the texture. /// The extents of the texture. - /// Keep alive or not. /// Manager that we obtained this from. - internal TextureManagerTextureWrap(string path, Vector2 extents, bool keepAlive, TextureManager manager) + internal TextureManagerTextureWrap(string path, Vector2 extents, TextureManager manager) { this.path = path; - this.keepAlive = keepAlive; this.manager = manager; this.Width = (int)extents.X; this.Height = (int)extents.Y; @@ -648,12 +504,7 @@ internal class TextureManagerTextureWrap : IDalamudTextureWrap /// public void Dispose() { - lock (this) - { - if (!this.IsDisposed) - this.manager.NotifyTextureDisposed(this.path, this.keepAlive); - - this.IsDisposed = true; - } + this.IsDisposed = true; + // This is a no-op. The manager cleans up textures that are not being drawn. } } diff --git a/Dalamud/Plugin/Services/ITextureProvider.cs b/Dalamud/Plugin/Services/ITextureProvider.cs index 091b2ed67..f91d4ee8e 100644 --- a/Dalamud/Plugin/Services/ITextureProvider.cs +++ b/Dalamud/Plugin/Services/ITextureProvider.cs @@ -44,7 +44,7 @@ public interface ITextureProvider /// If null, default to the game's current language. /// /// - /// Prevent Dalamud from automatically unloading this icon to save memory. Usually does not need to be set. + /// Not used. This parameter is ignored. /// /// /// Null, if the icon does not exist in the specified configuration, or a texture wrap that can be used @@ -72,7 +72,7 @@ public interface ITextureProvider /// You may only specify paths in the game's VFS. /// /// The path to the texture in the game's VFS. - /// Prevent Dalamud from automatically unloading this texture to save memory. Usually does not need to be set. + /// Not used. This parameter is ignored. /// Null, if the icon does not exist, or a texture wrap that can be used to render the texture. public IDalamudTextureWrap? GetTextureFromGame(string path, bool keepAlive = false); @@ -83,7 +83,7 @@ public interface ITextureProvider /// This API can load .png and .tex files. /// /// The FileInfo describing the image or texture file. - /// Prevent Dalamud from automatically unloading this texture to save memory. Usually does not need to be set. + /// Not used. This parameter is ignored. /// Null, if the file does not exist, or a texture wrap that can be used to render the texture. public IDalamudTextureWrap? GetTextureFromFile(FileInfo file, bool keepAlive = false); From acb81deb9c073829ff22c5c895096c3d1f079750 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 23 Sep 2023 17:45:50 +0200 Subject: [PATCH 094/120] make sure that access is completely atomic --- Dalamud/Interface/Internal/TextureManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 542299656..7c773bd36 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -305,12 +305,12 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe if (info == null) throw new Exception("null info in activeTextures"); - } - - info.LastAccess = DateTime.UtcNow; + + info.LastAccess = DateTime.UtcNow; - if (info is { Wrap: not null }) - return info; + if (info is { Wrap: not null }) + return info; + } if (!this.im.IsReady) throw new InvalidOperationException("Cannot create textures before scene is ready"); From ebabb7bd049e8e428bfdc476811f723ca7882ded Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 24 Sep 2023 01:40:56 +0200 Subject: [PATCH 095/120] chore: make SigScanner public, have separate service TargetSigScanner that resolves via ISigScanner (closes #1426) --- Dalamud/Dalamud.cs | 2 +- .../Game/Addon/Events/AddonEventManager.cs | 2 +- .../Game/Addon/Lifecycle/AddonLifecycle.cs | 2 +- Dalamud/Game/BaseAddressResolver.cs | 9 ------ Dalamud/Game/ClientState/ClientState.cs | 2 +- Dalamud/Game/ClientState/Keys/KeyState.cs | 2 +- Dalamud/Game/Config/GameConfig.cs | 2 +- Dalamud/Game/DutyState/DutyState.cs | 2 +- Dalamud/Game/Framework.cs | 2 +- Dalamud/Game/Gui/ChatGui.cs | 2 +- Dalamud/Game/Gui/FlyText/FlyTextGui.cs | 2 +- Dalamud/Game/Gui/GameGui.cs | 2 +- .../Game/Gui/PartyFinder/PartyFinderGui.cs | 2 +- Dalamud/Game/Gui/Toast/ToastGui.cs | 2 +- Dalamud/Game/Internal/AntiDebug.cs | 2 +- Dalamud/Game/Internal/DalamudAtkTweaks.cs | 2 +- Dalamud/Game/Libc/LibcFunction.cs | 2 +- Dalamud/Game/Network/GameNetwork.cs | 2 +- Dalamud/Game/SigScanner.cs | 7 +---- Dalamud/Game/TargetSigScanner.cs | 28 +++++++++++++++++++ .../GameInteropProviderPluginScoped.cs | 2 +- .../Interface/Internal/InterfaceManager.cs | 2 +- .../Windows/Data/Widgets/AddressesWidget.cs | 2 +- Dalamud/Plugin/Internal/PluginManager.cs | 2 +- Dalamud/ServiceManager.cs | 8 +++--- Dalamud/Utility/Signatures/SignatureHelper.cs | 2 +- 26 files changed, 55 insertions(+), 41 deletions(-) create mode 100644 Dalamud/Game/TargetSigScanner.cs diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index c38594771..a9d822f55 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -167,7 +167,7 @@ internal sealed class Dalamud : IServiceType internal void ReplaceExceptionHandler() { var releaseSig = "40 55 53 56 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ??"; - var releaseFilter = Service.Get().ScanText(releaseSig); + var releaseFilter = Service.Get().ScanText(releaseSig); Log.Debug($"SE debug filter at {releaseFilter.ToInt64():X}"); var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(releaseFilter); diff --git a/Dalamud/Game/Addon/Events/AddonEventManager.cs b/Dalamud/Game/Addon/Events/AddonEventManager.cs index 8ec77b10d..a91f5437c 100644 --- a/Dalamud/Game/Addon/Events/AddonEventManager.cs +++ b/Dalamud/Game/Addon/Events/AddonEventManager.cs @@ -41,7 +41,7 @@ internal unsafe class AddonEventManager : IDisposable, IServiceType private AddonCursorType? cursorOverride; [ServiceManager.ServiceConstructor] - private AddonEventManager(SigScanner sigScanner) + private AddonEventManager(TargetSigScanner sigScanner) { this.address = new AddonEventManagerAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs b/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs index f1ee69f2b..d4e45688d 100644 --- a/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs +++ b/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs @@ -38,7 +38,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType private readonly List eventListeners = new(); [ServiceManager.ServiceConstructor] - private AddonLifecycle(SigScanner sigScanner) + private AddonLifecycle(TargetSigScanner sigScanner) { this.address = new AddonLifecycleAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/BaseAddressResolver.cs b/Dalamud/Game/BaseAddressResolver.cs index 9935aac7b..cd1ef8fd2 100644 --- a/Dalamud/Game/BaseAddressResolver.cs +++ b/Dalamud/Game/BaseAddressResolver.cs @@ -22,15 +22,6 @@ internal abstract class BaseAddressResolver /// protected bool IsResolved { get; set; } - /// - /// Setup the resolver, calling the appropriate method based on the process architecture, - /// using the default SigScanner. - /// - /// For plugins. Not intended to be called from Dalamud Service{T} constructors. - /// - [UsedImplicitly] - public void Setup() => this.Setup(Service.Get()); - /// /// Setup the resolver, calling the appropriate method based on the process architecture. /// diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index baf6f6634..ccb87ff0e 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -41,7 +41,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState private bool lastFramePvP; [ServiceManager.ServiceConstructor] - private ClientState(SigScanner sigScanner, DalamudStartInfo startInfo, GameLifecycle lifecycle) + private ClientState(TargetSigScanner sigScanner, DalamudStartInfo startInfo, GameLifecycle lifecycle) { this.lifecycle = lifecycle; this.address = new ClientStateAddressResolver(); diff --git a/Dalamud/Game/ClientState/Keys/KeyState.cs b/Dalamud/Game/ClientState/Keys/KeyState.cs index 03c5d59b9..76bee51bf 100644 --- a/Dalamud/Game/ClientState/Keys/KeyState.cs +++ b/Dalamud/Game/ClientState/Keys/KeyState.cs @@ -39,7 +39,7 @@ internal class KeyState : IServiceType, IKeyState private VirtualKey[]? validVirtualKeyCache; [ServiceManager.ServiceConstructor] - private KeyState(SigScanner sigScanner, ClientState clientState) + private KeyState(TargetSigScanner sigScanner, ClientState clientState) { var moduleBaseAddress = sigScanner.Module.BaseAddress; var addressResolver = clientState.AddressResolver; diff --git a/Dalamud/Game/Config/GameConfig.cs b/Dalamud/Game/Config/GameConfig.cs index 831c1157b..ea988525c 100644 --- a/Dalamud/Game/Config/GameConfig.cs +++ b/Dalamud/Game/Config/GameConfig.cs @@ -19,7 +19,7 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable private Hook? configChangeHook; [ServiceManager.ServiceConstructor] - private unsafe GameConfig(Framework framework, SigScanner sigScanner) + private unsafe GameConfig(Framework framework, TargetSigScanner sigScanner) { framework.RunOnTick(() => { diff --git a/Dalamud/Game/DutyState/DutyState.cs b/Dalamud/Game/DutyState/DutyState.cs index 3890a1f8b..6dda95a66 100644 --- a/Dalamud/Game/DutyState/DutyState.cs +++ b/Dalamud/Game/DutyState/DutyState.cs @@ -28,7 +28,7 @@ internal unsafe class DutyState : IDisposable, IServiceType, IDutyState private readonly ClientState.ClientState clientState = Service.Get(); [ServiceManager.ServiceConstructor] - private DutyState(SigScanner sigScanner) + private DutyState(TargetSigScanner sigScanner) { this.address = new DutyStateAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Framework.cs b/Dalamud/Game/Framework.cs index 08b97edbc..22343fd8e 100644 --- a/Dalamud/Game/Framework.cs +++ b/Dalamud/Game/Framework.cs @@ -51,7 +51,7 @@ internal sealed class Framework : IDisposable, IServiceType, IFramework private Thread? frameworkUpdateThread; [ServiceManager.ServiceConstructor] - private Framework(SigScanner sigScanner, GameLifecycle lifecycle) + private Framework(TargetSigScanner sigScanner, GameLifecycle lifecycle) { this.lifecycle = lifecycle; this.hitchDetector = new HitchDetector("FrameworkUpdate", this.configuration.FrameworkUpdateHitch); diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs index 55c919ab5..5bf6232fa 100644 --- a/Dalamud/Game/Gui/ChatGui.cs +++ b/Dalamud/Game/Gui/ChatGui.cs @@ -42,7 +42,7 @@ internal sealed class ChatGui : IDisposable, IServiceType, IChatGui private IntPtr baseAddress = IntPtr.Zero; [ServiceManager.ServiceConstructor] - private ChatGui(SigScanner sigScanner) + private ChatGui(TargetSigScanner sigScanner) { this.address = new ChatGuiAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Gui/FlyText/FlyTextGui.cs b/Dalamud/Game/Gui/FlyText/FlyTextGui.cs index 64de4b2dd..3da8dc2a9 100644 --- a/Dalamud/Game/Gui/FlyText/FlyTextGui.cs +++ b/Dalamud/Game/Gui/FlyText/FlyTextGui.cs @@ -30,7 +30,7 @@ internal sealed class FlyTextGui : IDisposable, IServiceType, IFlyTextGui private readonly Hook createFlyTextHook; [ServiceManager.ServiceConstructor] - private FlyTextGui(SigScanner sigScanner) + private FlyTextGui(TargetSigScanner sigScanner) { this.Address = new FlyTextGuiAddressResolver(); this.Address.Setup(sigScanner); diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 349d2a424..9796effc5 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -48,7 +48,7 @@ internal sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui private OpenMapWithFlagDelegate? openMapWithFlag; [ServiceManager.ServiceConstructor] - private GameGui(SigScanner sigScanner) + private GameGui(TargetSigScanner sigScanner) { this.address = new GameGuiAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs index 4bd93cdf0..61c0f62e4 100644 --- a/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs +++ b/Dalamud/Game/Gui/PartyFinder/PartyFinderGui.cs @@ -27,7 +27,7 @@ internal sealed class PartyFinderGui : IDisposable, IServiceType, IPartyFinderGu /// /// Sig scanner to use. [ServiceManager.ServiceConstructor] - private PartyFinderGui(SigScanner sigScanner) + private PartyFinderGui(TargetSigScanner sigScanner) { this.address = new PartyFinderAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Gui/Toast/ToastGui.cs b/Dalamud/Game/Gui/Toast/ToastGui.cs index 9624e3e72..362edb3be 100644 --- a/Dalamud/Game/Gui/Toast/ToastGui.cs +++ b/Dalamud/Game/Gui/Toast/ToastGui.cs @@ -33,7 +33,7 @@ internal sealed partial class ToastGui : IDisposable, IServiceType, IToastGui /// /// Sig scanner to use. [ServiceManager.ServiceConstructor] - private ToastGui(SigScanner sigScanner) + private ToastGui(TargetSigScanner sigScanner) { this.address = new ToastGuiAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Internal/AntiDebug.cs b/Dalamud/Game/Internal/AntiDebug.cs index ba482ef48..2f4ec28c0 100644 --- a/Dalamud/Game/Internal/AntiDebug.cs +++ b/Dalamud/Game/Internal/AntiDebug.cs @@ -19,7 +19,7 @@ internal sealed partial class AntiDebug : IServiceType private IntPtr debugCheckAddress; [ServiceManager.ServiceConstructor] - private AntiDebug(SigScanner sigScanner) + private AntiDebug(TargetSigScanner sigScanner) { try { diff --git a/Dalamud/Game/Internal/DalamudAtkTweaks.cs b/Dalamud/Game/Internal/DalamudAtkTweaks.cs index 60e61b2f7..b45b35c4d 100644 --- a/Dalamud/Game/Internal/DalamudAtkTweaks.cs +++ b/Dalamud/Game/Internal/DalamudAtkTweaks.cs @@ -41,7 +41,7 @@ internal sealed unsafe partial class DalamudAtkTweaks : IServiceType private readonly string locDalamudSettings; [ServiceManager.ServiceConstructor] - private DalamudAtkTweaks(SigScanner sigScanner) + private DalamudAtkTweaks(TargetSigScanner sigScanner) { var openSystemMenuAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 32 C0 4C 8B AC 24 ?? ?? ?? ?? 48 8B 8D ?? ?? ?? ??"); diff --git a/Dalamud/Game/Libc/LibcFunction.cs b/Dalamud/Game/Libc/LibcFunction.cs index b0bd4950c..f1cd07080 100644 --- a/Dalamud/Game/Libc/LibcFunction.cs +++ b/Dalamud/Game/Libc/LibcFunction.cs @@ -24,7 +24,7 @@ internal sealed class LibcFunction : IServiceType, ILibcFunction private readonly StdStringDeallocateDelegate stdStringDeallocate; [ServiceManager.ServiceConstructor] - private LibcFunction(SigScanner sigScanner) + private LibcFunction(TargetSigScanner sigScanner) { this.address = new LibcFunctionAddressResolver(); this.address.Setup(sigScanner); diff --git a/Dalamud/Game/Network/GameNetwork.cs b/Dalamud/Game/Network/GameNetwork.cs index 7c900ece4..9ea3e491e 100644 --- a/Dalamud/Game/Network/GameNetwork.cs +++ b/Dalamud/Game/Network/GameNetwork.cs @@ -30,7 +30,7 @@ internal sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork private IntPtr baseAddress; [ServiceManager.ServiceConstructor] - private GameNetwork(SigScanner sigScanner) + private GameNetwork(TargetSigScanner sigScanner) { this.hitchDetectorUp = new HitchDetector("GameNetworkUp", this.configuration.GameNetworkUpHitch); this.hitchDetectorDown = new HitchDetector("GameNetworkDown", this.configuration.GameNetworkDownHitch); diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs index ace4654be..fe2d9083e 100644 --- a/Dalamud/Game/SigScanner.cs +++ b/Dalamud/Game/SigScanner.cs @@ -20,12 +20,7 @@ namespace Dalamud.Game; /// /// A SigScanner facilitates searching for memory signatures in a given ProcessModule. /// -[PluginInterface] -[InterfaceVersion("1.0")] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 -internal class SigScanner : IDisposable, IServiceType, ISigScanner +public class SigScanner : IDisposable, ISigScanner { private readonly FileInfo? cacheFile; diff --git a/Dalamud/Game/TargetSigScanner.cs b/Dalamud/Game/TargetSigScanner.cs new file mode 100644 index 000000000..0360f95cc --- /dev/null +++ b/Dalamud/Game/TargetSigScanner.cs @@ -0,0 +1,28 @@ +using System.Diagnostics; +using System.IO; + +using Dalamud.IoC; +using Dalamud.IoC.Internal; + +namespace Dalamud.Game; + +/// +/// A SigScanner facilitates searching for memory signatures in a given ProcessModule. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class TargetSigScanner : SigScanner, IServiceType +{ + /// + /// Initializes a new instance of the class. + /// + /// Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks. + /// File used to cached signatures. + public TargetSigScanner(bool doCopy = false, FileInfo? cacheFile = null) + : base(Process.GetCurrentProcess().MainModule!, doCopy, cacheFile) + { + } +} diff --git a/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs b/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs index 96172e5b2..59f2d2684 100644 --- a/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs +++ b/Dalamud/Hooking/Internal/GameInteropProviderPluginScoped.cs @@ -33,7 +33,7 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT /// /// Plugin this instance belongs to. /// SigScanner instance for target module. - public GameInteropProviderPluginScoped(LocalPlugin plugin, SigScanner scanner) + public GameInteropProviderPluginScoped(LocalPlugin plugin, TargetSigScanner scanner) { this.plugin = plugin; this.scanner = scanner; diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index be6ca3528..d00f33180 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -1055,7 +1055,7 @@ internal class InterfaceManager : IDisposable, IServiceType } [ServiceManager.CallWhenServicesReady] - private void ContinueConstruction(SigScanner sigScanner, Framework framework) + private void ContinueConstruction(TargetSigScanner sigScanner, Framework framework) { this.address.Setup(sigScanner); framework.RunOnFrameworkThread(() => diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs index 0955c1183..dfa6f173d 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/AddressesWidget.cs @@ -36,7 +36,7 @@ internal class AddressesWidget : IDataWindowWidget { try { - var sigScanner = Service.Get(); + var sigScanner = Service.Get(); this.sigResult = sigScanner.ScanText(this.inputSig); } catch (KeyNotFoundException) diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 691d5f729..f91d4cd56 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -623,7 +623,7 @@ internal partial class PluginManager : IDisposable, IServiceType Log.Error(e, "Failed to load at least one plugin"); } - var sigScanner = await Service.GetAsync().ConfigureAwait(false); + var sigScanner = await Service.GetAsync().ConfigureAwait(false); this.PluginsReady = true; this.NotifyinstalledPluginsListChanged(); sigScanner.Save(); diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index d1c1002bd..ecb58d48b 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -105,15 +105,15 @@ internal static class ServiceManager Service.Provide(new ServiceContainer()); LoadedServices.Add(typeof(ServiceContainer)); - Service.Provide( - new SigScanner( + Service.Provide( + new TargetSigScanner( true, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}.json")))); - LoadedServices.Add(typeof(SigScanner)); + LoadedServices.Add(typeof(TargetSigScanner)); } using (Timings.Start("CS Resolver Init")) { - FFXIVClientStructs.Interop.Resolver.GetInstance.SetupSearchSpace(Service.Get().SearchBase, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}_cs.json"))); + FFXIVClientStructs.Interop.Resolver.GetInstance.SetupSearchSpace(Service.Get().SearchBase, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}_cs.json"))); FFXIVClientStructs.Interop.Resolver.GetInstance.Resolve(); } } diff --git a/Dalamud/Utility/Signatures/SignatureHelper.cs b/Dalamud/Utility/Signatures/SignatureHelper.cs index e2c9926a8..51f59bba2 100755 --- a/Dalamud/Utility/Signatures/SignatureHelper.cs +++ b/Dalamud/Utility/Signatures/SignatureHelper.cs @@ -29,7 +29,7 @@ internal static class SignatureHelper /// Collection of created IDalamudHooks. internal static IEnumerable Initialize(object self, bool log = true) { - var scanner = Service.Get(); + var scanner = Service.Get(); var selfType = self.GetType(); var fields = selfType.GetFields(Flags).Select(field => (IFieldOrPropertyInfo)new FieldInfoWrapper(field)) .Concat(selfType.GetProperties(Flags).Select(prop => new PropertyInfoWrapper(prop))) From f96ab7aa90773bbc5da5ce4288c5a243954fd1ce Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 24 Sep 2023 01:45:46 +0200 Subject: [PATCH 096/120] fix warnings --- Dalamud/Game/Config/GameConfig.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dalamud/Game/Config/GameConfig.cs b/Dalamud/Game/Config/GameConfig.cs index ea988525c..ae3205abc 100644 --- a/Dalamud/Game/Config/GameConfig.cs +++ b/Dalamud/Game/Config/GameConfig.cs @@ -41,6 +41,7 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable /// public event EventHandler? Changed; +#pragma warning disable 67 /// /// Unused internally, used as a proxy for System.Changed via GameConfigPluginScoped /// @@ -55,6 +56,7 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable /// Unused internally, used as a proxy for UiControl.Changed via GameConfigPluginScoped /// public event EventHandler? UiControlChanged; +#pragma warning restore 67 /// public GameConfigSection System { get; private set; } From 34c05adeb13e4bf8d51d39064f476479735cc1fb Mon Sep 17 00:00:00 2001 From: KazWolfe Date: Sat, 23 Sep 2023 19:58:21 -0700 Subject: [PATCH 097/120] Remove IPluginLog#Logger for now (#1428) - Causes issues with mocking. --- Dalamud/Plugin/Services/IPluginLog.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Dalamud/Plugin/Services/IPluginLog.cs b/Dalamud/Plugin/Services/IPluginLog.cs index d16e985af..aac321092 100644 --- a/Dalamud/Plugin/Services/IPluginLog.cs +++ b/Dalamud/Plugin/Services/IPluginLog.cs @@ -20,15 +20,6 @@ public interface IPluginLog /// LogEventLevel MinimumLogLevel { get; set; } - /// - /// Gets an instance of the Serilog for advanced use cases. The provided logger will handle - /// tagging all log messages with the appropriate context variables and properties. - /// - /// - /// Not currently part of public API - will be added after some formatter work has been completed. - /// - internal ILogger Logger { get; } - /// /// Log a message to the Dalamud log for this plugin. This log level should be /// used primarily for unrecoverable errors or critical faults in a plugin. From 6a3e4906f3156a77948cf08b165de1e27415908a Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 23 Sep 2023 23:53:25 -0700 Subject: [PATCH 098/120] Fix bug, and simplify logic --- Dalamud/Game/Gui/GameGui.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 9796effc5..a1a17436e 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -484,15 +484,16 @@ internal sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui return retVal; } - private IntPtr ToggleUiHideDetour(IntPtr thisPtr, bool uiVisible) + private IntPtr ToggleUiHideDetour(IntPtr thisPtr, bool unknownByte) { - this.GameUiHidden = !RaptureAtkModule.Instance()->IsUiVisible; + var result = this.toggleUiHideHook.Original(thisPtr, unknownByte); + this.GameUiHidden = !RaptureAtkModule.Instance()->IsUiVisible; this.UiHideToggled?.InvokeSafely(this, this.GameUiHidden); Log.Debug("UiHide toggled: {0}", this.GameUiHidden); - return this.toggleUiHideHook.Original(thisPtr, uiVisible); + return result; } private char HandleImmDetour(IntPtr framework, char a2, byte a3) From 02daff2543334c36239eb89502b229d4d98bb9a3 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Mon, 25 Sep 2023 21:48:35 -0700 Subject: [PATCH 099/120] Add clipped draw for drawing rows with multiple items per row --- Dalamud/Interface/Utility/ImGuiClip.cs | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Dalamud/Interface/Utility/ImGuiClip.cs b/Dalamud/Interface/Utility/ImGuiClip.cs index e36970885..fafd026f0 100644 --- a/Dalamud/Interface/Utility/ImGuiClip.cs +++ b/Dalamud/Interface/Utility/ImGuiClip.cs @@ -59,6 +59,56 @@ public static class ImGuiClip clipper.Destroy(); } + /// + /// Draws the enumerable data with number of items per line. + /// + /// Enumerable containing data to draw. + /// The function to draw a single item. + /// How many items to draw per line. + /// How tall each line is. + /// The type of data to draw. + public static void ClippedDraw(IReadOnlyList data, Action draw, int itemsPerLine, float lineHeight) + { + ImGuiListClipperPtr clipper; + unsafe + { + clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper()); + } + + var maxRows = (int)MathF.Ceiling((float)data.Count / itemsPerLine); + + clipper.Begin(maxRows, lineHeight); + while (clipper.Step()) + { + for (var actualRow = clipper.DisplayStart; actualRow < clipper.DisplayEnd; actualRow++) + { + if (actualRow >= maxRows) + return; + + if (actualRow < 0) + continue; + + var itemsForRow = data + .Skip(actualRow * itemsPerLine) + .Take(itemsPerLine); + + var currentIndex = 0; + foreach (var item in itemsForRow) + { + if (currentIndex++ != 0 && currentIndex < itemsPerLine + 1) + { + ImGui.SameLine(); + } + + draw(item); + } + } + } + + clipper.End(); + clipper.Destroy(); + } + // Draw a clipped random-access collection of consistent height lineHeight. // Uses ImGuiListClipper and thus handles start- and end-dummies itself, but acts on type and index. public static void ClippedDraw(IReadOnlyList data, Action draw, float lineHeight) From 3e3f0e632b9f3c576684a01b824be115de72d05d Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Tue, 26 Sep 2023 10:50:26 -0700 Subject: [PATCH 100/120] Fix Notification Window not showing with multimonitor mode enabled. --- Dalamud/Interface/Internal/Notifications/NotificationManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Interface/Internal/Notifications/NotificationManager.cs b/Dalamud/Interface/Internal/Notifications/NotificationManager.cs index 9d20d6d3e..67ad3ee8f 100644 --- a/Dalamud/Interface/Internal/Notifications/NotificationManager.cs +++ b/Dalamud/Interface/Internal/Notifications/NotificationManager.cs @@ -106,7 +106,7 @@ internal class NotificationManager : IServiceType ImGuiHelpers.ForceNextWindowMainViewport(); ImGui.SetNextWindowBgAlpha(opacity); - ImGui.SetNextWindowPos(new Vector2(viewportSize.X - NotifyPaddingX, viewportSize.Y - NotifyPaddingY - height), ImGuiCond.Always, Vector2.One); + ImGui.SetNextWindowPos(ImGuiHelpers.MainViewport.Pos + new Vector2(viewportSize.X - NotifyPaddingX, viewportSize.Y - NotifyPaddingY - height), ImGuiCond.Always, Vector2.One); ImGui.Begin(windowName, NotifyToastFlags); ImGui.PushTextWrapPos(viewportSize.X / 3.0f); From 125034155b01fe34a59d065fc3a8670dc647ec3f Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 27 Sep 2023 22:10:21 +0200 Subject: [PATCH 101/120] feat: first pass at ReliableFileStorage service --- .../Internal/DalamudConfiguration.cs | 35 +- Dalamud/Dalamud.cs | 6 +- Dalamud/Dalamud.csproj | 1 + Dalamud/EntryPoint.cs | 6 +- Dalamud/ServiceManager.cs | 7 +- Dalamud/Storage/ReliableFileStorage.cs | 337 ++++++++++++++++++ 6 files changed, 379 insertions(+), 13 deletions(-) create mode 100644 Dalamud/Storage/ReliableFileStorage.cs diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 2d0a08942..55bf82496 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -7,6 +7,7 @@ using System.Linq; using Dalamud.Game.Text; using Dalamud.Interface.Style; using Dalamud.Plugin.Internal.Profiles; +using Dalamud.Storage; using Dalamud.Utility; using Newtonsoft.Json; using Serilog; @@ -18,7 +19,7 @@ namespace Dalamud.Configuration.Internal; /// Class containing Dalamud settings. /// [Serializable] -internal sealed class DalamudConfiguration : IServiceType +internal sealed class DalamudConfiguration : IServiceType, IDisposable { private static readonly JsonSerializerSettings SerializerSettings = new() { @@ -422,23 +423,33 @@ internal sealed class DalamudConfiguration : IServiceType /// /// Load a configuration from the provided path. /// - /// The path to load the configuration file from. + /// Path to read from. + /// File storage. /// The deserialized configuration file. - public static DalamudConfiguration Load(string path) + public static DalamudConfiguration Load(string path, ReliableFileStorage fs) { DalamudConfiguration deserialized = null; + try { - deserialized = JsonConvert.DeserializeObject(File.ReadAllText(path), SerializerSettings); + fs.ReadAllText(path, text => + { + deserialized = + JsonConvert.DeserializeObject(text, SerializerSettings); + }); } - catch (Exception ex) + catch (FileNotFoundException) { - Log.Warning(ex, "Failed to load DalamudConfiguration at {0}", path); + // ignored + } + catch (Exception e) + { + Log.Error(e, "Could not load DalamudConfiguration at {Path}, creating new", path); } deserialized ??= new DalamudConfiguration(); deserialized.configPath = path; - + return deserialized; } @@ -457,6 +468,13 @@ internal sealed class DalamudConfiguration : IServiceType { this.Save(); } + + /// + public void Dispose() + { + // Make sure that we save, if a save is queued while we are shutting down + this.Update(); + } /// /// Save the file, if needed. Only needs to be done once a frame. @@ -476,7 +494,8 @@ internal sealed class DalamudConfiguration : IServiceType { ThreadSafety.AssertMainThread(); - Util.WriteAllTextSafe(this.configPath, JsonConvert.SerializeObject(this, SerializerSettings)); + Service.Get().WriteAllText( + this.configPath, JsonConvert.SerializeObject(this, SerializerSettings)); this.DalamudConfigurationSaved?.Invoke(this); } } diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index a9d822f55..2187f0da2 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -12,6 +12,7 @@ using Dalamud.Game; using Dalamud.Game.Gui.Internal; using Dalamud.Interface.Internal; using Dalamud.Plugin.Internal; +using Dalamud.Storage; using Dalamud.Utility; using PInvoke; using Serilog; @@ -40,14 +41,15 @@ internal sealed class Dalamud : IServiceType /// Initializes a new instance of the class. /// /// DalamudStartInfo instance. + /// ReliableFileStorage instance. /// The Dalamud configuration. /// Event used to signal the main thread to continue. - public Dalamud(DalamudStartInfo info, DalamudConfiguration configuration, IntPtr mainThreadContinueEvent) + public Dalamud(DalamudStartInfo info, ReliableFileStorage fs, DalamudConfiguration configuration, IntPtr mainThreadContinueEvent) { this.unloadSignal = new ManualResetEvent(false); this.unloadSignal.Reset(); - ServiceManager.InitializeProvidedServicesAndClientStructs(this, info, configuration); + ServiceManager.InitializeProvidedServicesAndClientStructs(this, info, fs, configuration); if (!configuration.IsResumeGameAfterPluginLoad) { diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 5093fbfe9..7ae97e1a6 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -77,6 +77,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 7ad794e42..6b53ee3a6 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -10,6 +10,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Logging.Internal; using Dalamud.Logging.Retention; using Dalamud.Plugin.Internal; +using Dalamud.Storage; using Dalamud.Support; using Dalamud.Utility; using Newtonsoft.Json; @@ -137,7 +138,8 @@ public sealed class EntryPoint SerilogEventSink.Instance.LogLine += SerilogOnLogLine; // Load configuration first to get some early persistent state, like log level - var configuration = DalamudConfiguration.Load(info.ConfigurationPath!); + var fs = new ReliableFileStorage(Path.GetDirectoryName(info.ConfigurationPath)!); + var configuration = DalamudConfiguration.Load(info.ConfigurationPath!, fs); // Set the appropriate logging level from the configuration if (!configuration.LogSynchronously) @@ -169,7 +171,7 @@ public sealed class EntryPoint if (!Util.IsWine()) InitSymbolHandler(info); - var dalamud = new Dalamud(info, configuration, mainThreadContinueEvent); + var dalamud = new Dalamud(info, fs, configuration, mainThreadContinueEvent); Log.Information("This is Dalamud - Core: {GitHash}, CS: {CsGitHash} [{CsVersion}]", Util.GetGitHash(), Util.GetGitHashClientStructs(), FFXIVClientStructs.Interop.Resolver.Version); dalamud.WaitForUnload(); diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index ecb58d48b..38dc7534f 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -11,6 +11,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Game; using Dalamud.IoC.Internal; using Dalamud.Logging.Internal; +using Dalamud.Storage; using Dalamud.Utility.Timing; using JetBrains.Annotations; @@ -83,8 +84,9 @@ internal static class ServiceManager /// /// Instance of . /// Instance of . + /// Instance of /// Instance of . - public static void InitializeProvidedServicesAndClientStructs(Dalamud dalamud, DalamudStartInfo startInfo, DalamudConfiguration configuration) + public static void InitializeProvidedServicesAndClientStructs(Dalamud dalamud, DalamudStartInfo startInfo, ReliableFileStorage fs, DalamudConfiguration configuration) { // Initialize the process information. var cacheDir = new DirectoryInfo(Path.Combine(startInfo.WorkingDirectory!, "cachedSigs")); @@ -98,6 +100,9 @@ internal static class ServiceManager Service.Provide(startInfo); LoadedServices.Add(typeof(DalamudStartInfo)); + + Service.Provide(fs); + LoadedServices.Add(typeof(ReliableFileStorage)); Service.Provide(configuration); LoadedServices.Add(typeof(DalamudConfiguration)); diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs new file mode 100644 index 000000000..14ab59143 --- /dev/null +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -0,0 +1,337 @@ +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +using Dalamud.Logging.Internal; +using PInvoke; +using SQLite; + +namespace Dalamud.Storage; + +/* + * TODO: A file that is read frequently, but written very rarely, might not have offline changes by users persisted + * into the backup database, since it is only written to the backup database when it is written to the filesystem. + */ + +/// +/// A service that provides a reliable file storage. +/// Implements a VFS that writes files to the disk, and additionally keeps files in a SQLite database +/// for journaling/backup purposes. +/// Consumers can choose to receive a backup if they think that the file is corrupt. +/// +/// +/// This is not an early-loaded service, as it is needed before they are initialized. +/// +public class ReliableFileStorage : IServiceType, IDisposable +{ + private static readonly ModuleLog Log = new("VFS"); + + private SQLiteConnection db; + + /// + /// Initializes a new instance of the class. + /// + /// Path to the VFS. + [ServiceManager.ServiceConstructor] + public ReliableFileStorage(string vfsDbPath) + { + var databasePath = Path.Combine(vfsDbPath, "dalamudVfs.db"); + + Log.Verbose("Initializing VFS database at {Path}", databasePath); + this.db = new SQLiteConnection(databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex); + this.db.CreateTable(); + } + + /// + /// Check if a file exists. + /// This will return true if the file does not exist on the filesystem, but in the transparent backup. + /// You must then use this instance to read the file to ensure consistency. + /// + /// The path to check. + /// The container to check in. + /// True if the file exists. + public bool Exists(string path, Guid containerId = default) + { + ArgumentException.ThrowIfNullOrEmpty(path); + + if (File.Exists(path)) + return true; + + // If the file doesn't actually exist on the FS, but it does in the DB, we can say YES and read operations will read from the DB instead + var normalizedPath = NormalizePath(path); + var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); + return file != null; + } + + /// + /// Write all text to a file. + /// + /// Path to write to. + /// The contents of the file. + /// Container to write to. + public void WriteAllText(string path, string? contents, Guid containerId = default) + => this.WriteAllText(path, contents, Encoding.UTF8, containerId); + + /// + /// Write all text to a file. + /// + /// Path to write to. + /// The contents of the file. + /// The encoding to write with. + /// Container to write to. + public void WriteAllText(string path, string? contents, Encoding encoding, Guid containerId = default) + { + var bytes = encoding.GetBytes(contents ?? string.Empty); + this.WriteAllBytes(path, bytes, containerId); + } + + /// + /// Write all bytes to a file. + /// + /// Path to write to. + /// The contents of the file. + /// Container to write to. + public void WriteAllBytes(string path, byte[] bytes, Guid containerId = default) + { + ArgumentException.ThrowIfNullOrEmpty(path); + + var normalizedPath = NormalizePath(path); + var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); + if (file == null) + { + file = new DbFile + { + ContainerId = containerId, + Path = normalizedPath, + Data = bytes, + }; + this.db.Insert(file); + } + else + { + file.Data = bytes; + this.db.Update(file); + } + + WriteFileReliably(path, bytes); + } + + /// + /// Read all text from a file. + /// If the file does not exist on the filesystem, a read is attempted from the backup. The backup is not + /// automatically written back to disk, however. + /// + /// The path to read from. + /// Whether or not the backup of the file should take priority. + /// The container to read from. + /// All text stored in this file. + /// Thrown if the file does not exist on the filesystem or in the backup. + public string ReadAllText(string path, bool forceBackup = false, Guid containerId = default) + => this.ReadAllText(path, Encoding.UTF8, forceBackup, containerId); + + /// + /// Read all text from a file. + /// If the file does not exist on the filesystem, a read is attempted from the backup. The backup is not + /// automatically written back to disk, however. + /// + /// The path to read from. + /// The encoding to read with. + /// Whether or not the backup of the file should take priority. + /// The container to read from. + /// All text stored in this file. + /// Thrown if the file does not exist on the filesystem or in the backup. + public string ReadAllText(string path, Encoding encoding, bool forceBackup = false, Guid containerId = default) + { + var bytes = this.ReadAllBytes(path, forceBackup, containerId); + return encoding.GetString(bytes); + } + + /// + /// Read all text from a file, and automatically try again with the backup if the file does not exist or + /// the function throws an exception. If the backup read also throws an exception, + /// or the file does not exist in the backup, a is thrown. + /// + /// The path to read from. + /// Lambda that reads the file. Throw here to automatically attempt a read from the backup. + /// The container to read from. + /// Thrown if the file does not exist on the filesystem or in the backup. + /// Thrown here if the file and the backup fail their read. + public void ReadAllText(string path, Action reader, Guid containerId = default) + => this.ReadAllText(path, Encoding.UTF8, reader, containerId); + + /// + /// Read all text from a file, and automatically try again with the backup if the file does not exist or + /// the function throws an exception. If the backup read also throws an exception, + /// or the file does not exist in the backup, a is thrown. + /// + /// The path to read from. + /// The encoding to read with. + /// Lambda that reads the file. Throw here to automatically attempt a read from the backup. + /// The container to read from. + /// Thrown if the file does not exist on the filesystem or in the backup. + /// Thrown here if the file and the backup fail their read. + public void ReadAllText(string path, Encoding encoding, Action reader, Guid containerId = default) + { + ArgumentException.ThrowIfNullOrEmpty(path); + + // TODO: We are technically reading one time too many here, if the file does not exist on the FS, ReadAllText + // fails over to the backup, and then the backup fails to read in the lambda. We should do something about that, + // but it's not a big deal. Would be nice if ReadAllText could indicate if it did fail over. + + // 1.) Try without using the backup + try + { + var text = this.ReadAllText(path, encoding, false, containerId); + reader(text); + return; + } + catch (FileNotFoundException) + { + // We can't do anything about this. + throw; + } + catch (Exception ex) + { + Log.Verbose(ex, "First chance read from {Path} failed, trying backup", path); + } + + // 2.) Try using the backup + try + { + var text = this.ReadAllText(path, encoding, true, containerId); + reader(text); + } + catch (Exception ex) + { + Log.Error(ex, "Second chance read from {Path} failed, giving up", path); + throw new FileReadException(ex); + } + } + + /// + /// Read all bytes from a file. + /// If the file does not exist on the filesystem, a read is attempted from the backup. The backup is not + /// automatically written back to disk, however. + /// + /// The path to read from. + /// Whether or not the backup of the file should take priority. + /// The container to read from. + /// All bytes stored in this file. + /// Thrown if the file does not exist on the filesystem or in the backup. + public byte[] ReadAllBytes(string path, bool forceBackup = false, Guid containerId = default) + { + ArgumentException.ThrowIfNullOrEmpty(path); + + if (forceBackup) + { + var normalizedPath = NormalizePath(path); + var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); + if (file == null) + throw new FileNotFoundException(); + + return file.Data; + } + + // If the file doesn't exist, immediately check the backup db + if (!File.Exists(path)) + return this.ReadAllBytes(path, true, containerId); + + try + { + return File.ReadAllBytes(path); + } + catch (Exception e) + { + Log.Error(e, "Failed to read file from disk, falling back to database"); + return this.ReadAllBytes(path, true, containerId); + } + } + + /// + public void Dispose() + { + this.db.Dispose(); + } + + private static void WriteFileReliably(string path, byte[] bytes) + { + ArgumentException.ThrowIfNullOrEmpty(path); + + // Open the temp file + var tempPath = path + ".tmp"; + + using var tempFile = Kernel32 + .CreateFile(tempPath.AsSpan(), + new Kernel32.ACCESS_MASK(Kernel32.FileAccess.FILE_GENERIC_READ | Kernel32.FileAccess.FILE_GENERIC_WRITE), + Kernel32.FileShare.None, + null, + Kernel32.CreationDisposition.CREATE_ALWAYS, + Kernel32.CreateFileFlags.FILE_ATTRIBUTE_NORMAL, + Kernel32.SafeObjectHandle.Null); + + if (tempFile.IsInvalid) + throw new Win32Exception(); + + // Write the data + var bytesWritten = Kernel32.WriteFile(tempFile, new ArraySegment(bytes)); + if (bytesWritten != bytes.Length) + throw new Exception($"Could not write all bytes to temp file ({bytesWritten} of {bytes.Length})"); + + if (!Kernel32.FlushFileBuffers(tempFile)) + throw new Win32Exception(); + + tempFile.Close(); + + if (!MoveFileEx(tempPath, path, MoveFileFlags.MovefileReplaceExisting | MoveFileFlags.MovefileWriteThrough)) + throw new Win32Exception(); + } + + /// + /// Replace possible non-portable parts of a path with portable versions. + /// + /// The path to normalize. + /// The normalized path. + private static string NormalizePath(string path) + { + // Replace users folder + var usersFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + path = path.Replace(usersFolder, "%USERPROFILE%"); + + return path; + } + + [Flags] +#pragma warning disable SA1201 + private enum MoveFileFlags +#pragma warning restore SA1201 + { + MovefileReplaceExisting = 0x00000001, + MovefileWriteThrough = 0x00000008, + } + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] + private static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, + MoveFileFlags dwFlags); + + private class DbFile + { + [PrimaryKey] + [AutoIncrement] + public int Id { get; set; } + + public Guid ContainerId { get; set; } + + public string Path { get; set; } = null!; + + public byte[] Data { get; set; } = null!; + } +} + +public class FileReadException : Exception +{ + public FileReadException(Exception inner) + : base("Failed to read file", inner) + { + } +} From 1d8b579b040aebdf296c911c8e1d2d1f74f2444a Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 27 Sep 2023 22:33:58 +0200 Subject: [PATCH 102/120] feat: also use reliable storage for plugin configs --- .../Internal/DalamudConfiguration.cs | 4 + Dalamud/Configuration/PluginConfigurations.cs | 26 +++++-- Dalamud/Plugin/DalamudPluginInterface.cs | 2 +- Dalamud/Storage/ReliableFileStorage.cs | 51 +------------ Dalamud/Utility/Util.cs | 73 +++++++++++++++++-- 5 files changed, 94 insertions(+), 62 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 55bf82496..63494931c 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -436,6 +436,10 @@ internal sealed class DalamudConfiguration : IServiceType, IDisposable { deserialized = JsonConvert.DeserializeObject(text, SerializerSettings); + + // If this reads as null, the file was empty, that's no good + if (deserialized == null) + throw new Exception("Read config was null."); }); } catch (FileNotFoundException) diff --git a/Dalamud/Configuration/PluginConfigurations.cs b/Dalamud/Configuration/PluginConfigurations.cs index 957a7c99e..d1f926b0d 100644 --- a/Dalamud/Configuration/PluginConfigurations.cs +++ b/Dalamud/Configuration/PluginConfigurations.cs @@ -1,6 +1,6 @@ using System.IO; -using Dalamud.Utility; +using Dalamud.Storage; using Newtonsoft.Json; namespace Dalamud.Configuration; @@ -33,22 +33,36 @@ public sealed class PluginConfigurations /// Plugin name. public void Save(IPluginConfiguration config, string pluginName) { - Util.WriteAllTextSafe(this.GetConfigFile(pluginName).FullName, SerializeConfig(config)); + Service.Get() + .WriteAllText(this.GetConfigFile(pluginName).FullName, SerializeConfig(config)); } /// /// Load plugin configuration. /// /// Plugin name. + /// WorkingPluginID of the plugin. /// Plugin configuration. - public IPluginConfiguration? Load(string pluginName) + public IPluginConfiguration? Load(string pluginName, Guid workingPluginId) { var path = this.GetConfigFile(pluginName); - if (!path.Exists) - return null; + IPluginConfiguration? config = null; + try + { + Service.Get().ReadAllText(path.FullName, text => + { + config = DeserializeConfig(text); + if (config == null) + throw new Exception("Read config was null."); + }, workingPluginId); + } + catch (FileNotFoundException) + { + // ignored + } - return DeserializeConfig(File.ReadAllText(path.FullName)); + return config; } /// diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 6fdf875e5..0f5b4297c 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -370,7 +370,7 @@ public sealed class DalamudPluginInterface : IDisposable } // this shouldn't be a thing, I think, but just in case - return this.configs.Load(this.plugin.InternalName); + return this.configs.Load(this.plugin.InternalName, this.plugin.Manifest.WorkingPluginId); } /// diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index 14ab59143..32fba9aef 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; using System.Text; using Dalamud.Logging.Internal; +using Dalamud.Utility; using PInvoke; using SQLite; @@ -32,7 +33,6 @@ public class ReliableFileStorage : IServiceType, IDisposable /// Initializes a new instance of the class. /// /// Path to the VFS. - [ServiceManager.ServiceConstructor] public ReliableFileStorage(string vfsDbPath) { var databasePath = Path.Combine(vfsDbPath, "dalamudVfs.db"); @@ -113,7 +113,7 @@ public class ReliableFileStorage : IServiceType, IDisposable this.db.Update(file); } - WriteFileReliably(path, bytes); + Util.WriteAllBytesSafe(path, bytes); } /// @@ -252,39 +252,6 @@ public class ReliableFileStorage : IServiceType, IDisposable { this.db.Dispose(); } - - private static void WriteFileReliably(string path, byte[] bytes) - { - ArgumentException.ThrowIfNullOrEmpty(path); - - // Open the temp file - var tempPath = path + ".tmp"; - - using var tempFile = Kernel32 - .CreateFile(tempPath.AsSpan(), - new Kernel32.ACCESS_MASK(Kernel32.FileAccess.FILE_GENERIC_READ | Kernel32.FileAccess.FILE_GENERIC_WRITE), - Kernel32.FileShare.None, - null, - Kernel32.CreationDisposition.CREATE_ALWAYS, - Kernel32.CreateFileFlags.FILE_ATTRIBUTE_NORMAL, - Kernel32.SafeObjectHandle.Null); - - if (tempFile.IsInvalid) - throw new Win32Exception(); - - // Write the data - var bytesWritten = Kernel32.WriteFile(tempFile, new ArraySegment(bytes)); - if (bytesWritten != bytes.Length) - throw new Exception($"Could not write all bytes to temp file ({bytesWritten} of {bytes.Length})"); - - if (!Kernel32.FlushFileBuffers(tempFile)) - throw new Win32Exception(); - - tempFile.Close(); - - if (!MoveFileEx(tempPath, path, MoveFileFlags.MovefileReplaceExisting | MoveFileFlags.MovefileWriteThrough)) - throw new Win32Exception(); - } /// /// Replace possible non-portable parts of a path with portable versions. @@ -299,20 +266,6 @@ public class ReliableFileStorage : IServiceType, IDisposable return path; } - - [Flags] -#pragma warning disable SA1201 - private enum MoveFileFlags -#pragma warning restore SA1201 - { - MovefileReplaceExisting = 0x00000001, - MovefileWriteThrough = 0x00000008, - } - - [return: MarshalAs(UnmanagedType.Bool)] - [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] - private static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, - MoveFileFlags dwFlags); private class DbFile { diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 8ca87b691..36918abd2 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -20,6 +20,7 @@ using Dalamud.Logging.Internal; using Dalamud.Memory; using ImGuiNET; using Lumina.Excel.GeneratedSheets; +using PInvoke; using Serilog; namespace Dalamud.Utility; @@ -609,7 +610,7 @@ public static class Util } } } - + /// /// Overwrite text in a file by first writing it to a temporary file, and then /// moving that file to the path specified. @@ -618,12 +619,58 @@ public static class Util /// The text to write. public static void WriteAllTextSafe(string path, string text) { - var tmpPath = path + ".tmp"; - if (File.Exists(tmpPath)) - File.Delete(tmpPath); + WriteAllTextSafe(path, text, Encoding.UTF8); + } + + /// + /// Overwrite text in a file by first writing it to a temporary file, and then + /// moving that file to the path specified. + /// + /// The path of the file to write to. + /// The text to write. + /// Encoding to use. + public static void WriteAllTextSafe(string path, string text, Encoding encoding) + { + WriteAllBytesSafe(path, encoding.GetBytes(text)); + } + + /// + /// Overwrite data in a file by first writing it to a temporary file, and then + /// moving that file to the path specified. + /// + /// The path of the file to write to. + /// The data to write. + public static void WriteAllBytesSafe(string path, byte[] bytes) + { + ArgumentException.ThrowIfNullOrEmpty(path); + + // Open the temp file + var tempPath = path + ".tmp"; - File.WriteAllText(tmpPath, text); - File.Move(tmpPath, path, true); + using var tempFile = Kernel32 + .CreateFile(tempPath.AsSpan(), + new Kernel32.ACCESS_MASK(Kernel32.FileAccess.FILE_GENERIC_READ | Kernel32.FileAccess.FILE_GENERIC_WRITE), + Kernel32.FileShare.None, + null, + Kernel32.CreationDisposition.CREATE_ALWAYS, + Kernel32.CreateFileFlags.FILE_ATTRIBUTE_NORMAL, + Kernel32.SafeObjectHandle.Null); + + if (tempFile.IsInvalid) + throw new Win32Exception(); + + // Write the data + var bytesWritten = Kernel32.WriteFile(tempFile, new ArraySegment(bytes)); + if (bytesWritten != bytes.Length) + throw new Exception($"Could not write all bytes to temp file ({bytesWritten} of {bytes.Length})"); + + if (!Kernel32.FlushFileBuffers(tempFile)) + throw new Win32Exception(); + + tempFile.Close(); + + if (!MoveFileEx(tempPath, path, MoveFileFlags.MovefileReplaceExisting | MoveFileFlags.MovefileWriteThrough)) + throw new Win32Exception(); } /// @@ -762,4 +809,18 @@ public static class Util } } } + + [Flags] +#pragma warning disable SA1201 + private enum MoveFileFlags +#pragma warning restore SA1201 + { + MovefileReplaceExisting = 0x00000001, + MovefileWriteThrough = 0x00000008, + } + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] + private static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, + MoveFileFlags dwFlags); } From 63764cb669277fa79b097885657b85f3ff548035 Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 27 Sep 2023 22:41:25 +0200 Subject: [PATCH 103/120] chore: move exception to separate file --- Dalamud/ServiceManager.cs | 2 +- Dalamud/Storage/FileReadException.cs | 16 ++++++++++++++++ Dalamud/Storage/ReliableFileStorage.cs | 8 -------- 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 Dalamud/Storage/FileReadException.cs diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index 38dc7534f..f2ff864c3 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -84,7 +84,7 @@ internal static class ServiceManager /// /// Instance of . /// Instance of . - /// Instance of + /// Instance of . /// Instance of . public static void InitializeProvidedServicesAndClientStructs(Dalamud dalamud, DalamudStartInfo startInfo, ReliableFileStorage fs, DalamudConfiguration configuration) { diff --git a/Dalamud/Storage/FileReadException.cs b/Dalamud/Storage/FileReadException.cs new file mode 100644 index 000000000..09f7ff4fb --- /dev/null +++ b/Dalamud/Storage/FileReadException.cs @@ -0,0 +1,16 @@ +namespace Dalamud.Storage; + +/// +/// Thrown if all read operations fail. +/// +public class FileReadException : Exception +{ + /// + /// Initializes a new instance of the class. + /// + /// Inner error that caused this exception. + internal FileReadException(Exception inner) + : base("Failed to read file", inner) + { + } +} diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index 32fba9aef..43a32bf29 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -280,11 +280,3 @@ public class ReliableFileStorage : IServiceType, IDisposable public byte[] Data { get; set; } = null!; } } - -public class FileReadException : Exception -{ - public FileReadException(Exception inner) - : base("Failed to read file", inner) - { - } -} From f027b684eda6bc498a149a1ed39196834524da6f Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 27 Sep 2023 23:27:51 +0200 Subject: [PATCH 104/120] fix: specify WorkingPluginId when saving --- Dalamud/Configuration/PluginConfigurations.cs | 5 +++-- Dalamud/Plugin/DalamudPluginInterface.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Dalamud/Configuration/PluginConfigurations.cs b/Dalamud/Configuration/PluginConfigurations.cs index d1f926b0d..de5e071c1 100644 --- a/Dalamud/Configuration/PluginConfigurations.cs +++ b/Dalamud/Configuration/PluginConfigurations.cs @@ -31,10 +31,11 @@ public sealed class PluginConfigurations /// /// Plugin configuration. /// Plugin name. - public void Save(IPluginConfiguration config, string pluginName) + /// WorkingPluginId of the plugin. + public void Save(IPluginConfiguration config, string pluginName, Guid workingPluginId) { Service.Get() - .WriteAllText(this.GetConfigFile(pluginName).FullName, SerializeConfig(config)); + .WriteAllText(this.GetConfigFile(pluginName).FullName, SerializeConfig(config), workingPluginId); } /// diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 0f5b4297c..004b7196c 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -343,7 +343,7 @@ public sealed class DalamudPluginInterface : IDisposable if (currentConfig == null) return; - this.configs.Save(currentConfig, this.plugin.InternalName); + this.configs.Save(currentConfig, this.plugin.InternalName, this.plugin.Manifest.WorkingPluginId); } /// From c1fd08cc932097ee9cf298e2cba34399fe197862 Mon Sep 17 00:00:00 2001 From: goat Date: Thu, 28 Sep 2023 00:43:25 +0200 Subject: [PATCH 105/120] feat: wrap writes in a transaction --- Dalamud/Storage/ReliableFileStorage.cs | 35 ++++++++++++++------------ 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index 43a32bf29..fb75f3abd 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -95,25 +95,28 @@ public class ReliableFileStorage : IServiceType, IDisposable { ArgumentException.ThrowIfNullOrEmpty(path); - var normalizedPath = NormalizePath(path); - var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); - if (file == null) + this.db.RunInTransaction(() => { - file = new DbFile + var normalizedPath = NormalizePath(path); + var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); + if (file == null) { - ContainerId = containerId, - Path = normalizedPath, - Data = bytes, - }; - this.db.Insert(file); - } - else - { - file.Data = bytes; - this.db.Update(file); - } + file = new DbFile + { + ContainerId = containerId, + Path = normalizedPath, + Data = bytes, + }; + this.db.Insert(file); + } + else + { + file.Data = bytes; + this.db.Update(file); + } - Util.WriteAllBytesSafe(path, bytes); + Util.WriteAllBytesSafe(path, bytes); + }); } /// From 416bb42f5b91c7785f54ab13fa170d1422e47f0b Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 29 Sep 2023 18:37:45 +0200 Subject: [PATCH 106/120] feat: handle db load failures gracefully --- Dalamud/Storage/ReliableFileStorage.cs | 47 +++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index fb75f3abd..fec461cc3 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -27,7 +27,7 @@ public class ReliableFileStorage : IServiceType, IDisposable { private static readonly ModuleLog Log = new("VFS"); - private SQLiteConnection db; + private SQLiteConnection? db; /// /// Initializes a new instance of the class. @@ -38,8 +38,27 @@ public class ReliableFileStorage : IServiceType, IDisposable var databasePath = Path.Combine(vfsDbPath, "dalamudVfs.db"); Log.Verbose("Initializing VFS database at {Path}", databasePath); - this.db = new SQLiteConnection(databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex); - this.db.CreateTable(); + + try + { + this.SetupDb(vfsDbPath); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to load VFS database, starting fresh"); + + try + { + if (File.Exists(vfsDbPath)) + File.Delete(vfsDbPath); + } + catch (Exception) + { + // ignored + } + + this.SetupDb(vfsDbPath); + } } /// @@ -56,6 +75,9 @@ public class ReliableFileStorage : IServiceType, IDisposable if (File.Exists(path)) return true; + + if (this.db == null) + return false; // If the file doesn't actually exist on the FS, but it does in the DB, we can say YES and read operations will read from the DB instead var normalizedPath = NormalizePath(path); @@ -94,6 +116,12 @@ public class ReliableFileStorage : IServiceType, IDisposable public void WriteAllBytes(string path, byte[] bytes, Guid containerId = default) { ArgumentException.ThrowIfNullOrEmpty(path); + + if (this.db == null) + { + Util.WriteAllBytesSafe(path, bytes); + return; + } this.db.RunInTransaction(() => { @@ -227,6 +255,10 @@ public class ReliableFileStorage : IServiceType, IDisposable if (forceBackup) { + // If the db failed to load, act as if the file does not exist + if (this.db == null) + throw new FileNotFoundException("Backup database was not available"); + var normalizedPath = NormalizePath(path); var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); if (file == null) @@ -253,7 +285,7 @@ public class ReliableFileStorage : IServiceType, IDisposable /// public void Dispose() { - this.db.Dispose(); + this.db?.Dispose(); } /// @@ -269,6 +301,13 @@ public class ReliableFileStorage : IServiceType, IDisposable return path; } + + private void SetupDb(string path) + { + this.db = new SQLiteConnection(path, + SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex); + this.db.CreateTable(); + } private class DbFile { From 33abb5ec421c2d0bbe87896ae14af527cf5ba5fb Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 29 Sep 2023 18:39:36 +0200 Subject: [PATCH 107/120] chore: write manifests using new safer method --- Dalamud/Plugin/Internal/PluginManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index f91d4cd56..49608ac9b 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -836,7 +836,7 @@ internal partial class PluginManager : IDisposable, IServiceType 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)); + Util.WriteAllTextSafe(manifestFile.FullName, JsonConvert.SerializeObject(repoManifest, Formatting.Indented)); // Reload as a local manifest, add some attributes, and save again. var manifest = LocalPluginManifest.Load(manifestFile); From e9e234b340353ea6a636a61344938f4202bf6c48 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 29 Sep 2023 18:53:56 +0200 Subject: [PATCH 108/120] fix: actually use the correct path when setting up vfs, fix warnings use paramref instead of see fix warnings --- Dalamud/Interface/Utility/ImGuiClip.cs | 2 +- Dalamud/Logging/ScopedPluginLogService.cs | 4 +++- Dalamud/Storage/ReliableFileStorage.cs | 12 ++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Dalamud/Interface/Utility/ImGuiClip.cs b/Dalamud/Interface/Utility/ImGuiClip.cs index fafd026f0..c9321fe4c 100644 --- a/Dalamud/Interface/Utility/ImGuiClip.cs +++ b/Dalamud/Interface/Utility/ImGuiClip.cs @@ -60,7 +60,7 @@ public static class ImGuiClip } /// - /// Draws the enumerable data with number of items per line. + /// Draws the enumerable data with number of items per line. /// /// Enumerable containing data to draw. /// The function to draw a single item. diff --git a/Dalamud/Logging/ScopedPluginLogService.cs b/Dalamud/Logging/ScopedPluginLogService.cs index d6bb1f82d..ca96fa64a 100644 --- a/Dalamud/Logging/ScopedPluginLogService.cs +++ b/Dalamud/Logging/ScopedPluginLogService.cs @@ -48,7 +48,9 @@ public class ScopedPluginLogService : IServiceType, IPluginLog, IDisposable set => this.levelSwitch.MinimumLevel = value; } - /// + /// + /// Gets a logger that may be exposed to plugins some day. + /// public ILogger Logger { get; } /// diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index fec461cc3..7fdd04880 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -41,7 +41,7 @@ public class ReliableFileStorage : IServiceType, IDisposable try { - this.SetupDb(vfsDbPath); + this.SetupDb(databasePath); } catch (Exception ex) { @@ -49,15 +49,15 @@ public class ReliableFileStorage : IServiceType, IDisposable try { - if (File.Exists(vfsDbPath)) - File.Delete(vfsDbPath); + if (File.Exists(databasePath)) + File.Delete(databasePath); + + this.SetupDb(databasePath); } catch (Exception) { - // ignored + // ignored, we can run without one } - - this.SetupDb(vfsDbPath); } } From 4b9de312403990b5cdcfc4a9b5f32d4f3d355647 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 29 Sep 2023 20:47:54 +0200 Subject: [PATCH 109/120] fix: scoped services must register their dependencies with PluginManager to ensure the backing services are kept alive long enough --- Dalamud/IoC/Internal/ServiceContainer.cs | 3 +- Dalamud/ServiceManager.cs | 35 ++++--------- Dalamud/Service{T}.cs | 67 +++++++++++++++++++++--- 3 files changed, 72 insertions(+), 33 deletions(-) diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs index a82440029..3dd76473f 100644 --- a/Dalamud/IoC/Internal/ServiceContainer.cs +++ b/Dalamud/IoC/Internal/ServiceContainer.cs @@ -53,7 +53,6 @@ internal class ServiceContainer : IServiceProvider, IServiceType } this.instances[typeof(T)] = new(instance.ContinueWith(x => new WeakReference(x.Result)), typeof(T)); - this.RegisterInterfaces(typeof(T)); } /// @@ -69,7 +68,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType foreach (var resolvableType in resolveViaTypes) { Log.Verbose("=> {InterfaceName} provides for {TName}", resolvableType.FullName ?? "???", type.FullName ?? "???"); - + Debug.Assert(!this.interfaceToTypeMap.ContainsKey(resolvableType), "A service already implements this interface, this is not allowed"); Debug.Assert(type.IsAssignableTo(resolvableType), "Service does not inherit from indicated ResolveVia type"); diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index f2ff864c3..57e4ace10 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -145,12 +145,12 @@ internal static class ServiceManager if (serviceKind is ServiceKind.None) continue; - // Scoped service do not go through Service, so we must let ServiceContainer know what their interfaces map to - if (serviceKind is ServiceKind.ScopedService) - { - serviceContainer.RegisterInterfaces(serviceType); + // Let IoC know about the interfaces this service implements + serviceContainer.RegisterInterfaces(serviceType); + + // Scoped service do not go through Service and are never early loaded + if (serviceKind.HasFlag(ServiceKind.ScopedService)) continue; - } Debug.Assert( !serviceKind.HasFlag(ServiceKind.ManualService) && !serviceKind.HasFlag(ServiceKind.ScopedService), @@ -176,15 +176,10 @@ internal static class ServiceManager earlyLoadingServices.Add(serviceType); } - dependencyServicesMap[serviceType] = - (List)typeof(Service<>) - .MakeGenericType(serviceType) - .InvokeMember( - "GetDependencyServices", - BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, - null, - null, - null); + var typeAsServiceT = ServiceHelpers.GetAsService(serviceType); + dependencyServicesMap[serviceType] = ServiceHelpers.GetDependencies(typeAsServiceT) + .Select(x => typeof(Service<>).MakeGenericType(x)) + .ToList(); } _ = Task.Run(async () => @@ -327,16 +322,8 @@ internal static class ServiceManager Log.Verbose("Calling GetDependencyServices for '{ServiceName}'", serviceType.FullName!); - dependencyServicesMap[serviceType] = - ((List)typeof(Service<>) - .MakeGenericType(serviceType) - .InvokeMember( - "GetDependencyServices", - BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, - null, - null, - null))! - .Select(x => x.GetGenericArguments()[0]).ToList(); + var typeAsServiceT = ServiceHelpers.GetAsService(serviceType); + dependencyServicesMap[serviceType] = ServiceHelpers.GetDependencies(typeAsServiceT); allToUnload.Add(serviceType); } diff --git a/Dalamud/Service{T}.cs b/Dalamud/Service{T}.cs index aa10ead6e..539941c27 100644 --- a/Dalamud/Service{T}.cs +++ b/Dalamud/Service{T}.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -133,8 +134,8 @@ internal static class Service where T : IServiceType res.AddRange(typeof(T) .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Select(x => x.FieldType) - .Where(x => x.GetCustomAttribute(true) != null)); + .Where(x => x.GetCustomAttribute(true) != null) + .Select(x => x.FieldType)); res.AddRange(typeof(T) .GetCustomAttributes() @@ -148,13 +149,32 @@ internal static class Service where T : IServiceType { if (!serviceType.IsAssignableTo(typeof(IServiceType))) continue; - - var attr = serviceType.GetCustomAttribute(true); - if (attr == null) + + if (serviceType == typeof(PluginManager)) continue; - + // Scoped plugin services lifetime is tied to their scopes. They go away when LocalPlugin goes away. + // Nonetheless, their direct dependencies must be considered. if (serviceType.GetServiceKind() == ServiceManager.ServiceKind.ScopedService) + { + var typeAsServiceT = ServiceHelpers.GetAsService(serviceType); + var dependencies = ServiceHelpers.GetDependencies(typeAsServiceT); + ServiceManager.Log.Verbose("Found dependencies of scoped plugin service {Type} ({Cnt})", serviceType.FullName!, dependencies!.Count); + + foreach (var scopedDep in dependencies) + { + if (scopedDep == typeof(PluginManager)) + throw new Exception("Scoped plugin services cannot depend on PluginManager."); + + ServiceManager.Log.Verbose("PluginManager MUST depend on {Type} via {BaseType}", scopedDep.FullName!, serviceType.FullName!); + res.Add(scopedDep); + } + + continue; + } + + var pluginInterfaceAttribute = serviceType.GetCustomAttribute(true); + if (pluginInterfaceAttribute == null) continue; ServiceManager.Log.Verbose("PluginManager MUST depend on {Type}", serviceType.FullName!); @@ -164,7 +184,6 @@ internal static class Service where T : IServiceType return res .Distinct() - .Select(x => typeof(Service<>).MakeGenericType(x)) .ToList(); } @@ -295,3 +314,37 @@ internal static class Service where T : IServiceType } } } + +/// +/// Helper functions for services. +/// +internal static class ServiceHelpers +{ + /// + /// Get a list of dependencies for a service. Only accepts Service<T> types. + /// These are returned as Service<T> types. + /// + /// The dependencies for this service. + /// A list of dependencies. + public static List GetDependencies(Type serviceType) + { + return (List)serviceType.InvokeMember( + "GetDependencyServices", + BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, + null, + null, + null) ?? new List(); + } + + /// + /// Get the Service<T> type for a given service type. + /// This will throw if the service type is not a valid service. + /// + /// The type to obtain a Service<T> for. + /// The Service<T>. + public static Type GetAsService(Type type) + { + return typeof(Service<>) + .MakeGenericType(type); + } +} From 4a1b220d4a031a13304fbc798a19f342251f4af6 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 30 Sep 2023 01:09:25 +0200 Subject: [PATCH 110/120] fix: register interfaces for provided services --- Dalamud.CorePlugin/PluginImpl.cs | 5 ++- Dalamud.Injector/Hacks.cs | 20 +++++++++++ .../Internal/DalamudConfiguration.cs | 1 + Dalamud/Dalamud.cs | 1 + Dalamud/DalamudStartInfo.cs | 1 + Dalamud/Game/TargetSigScanner.cs | 1 + Dalamud/IoC/Internal/ServiceContainer.cs | 1 + Dalamud/ServiceManager.cs | 35 +++++++++---------- Dalamud/Storage/ReliableFileStorage.cs | 1 + 9 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 Dalamud.Injector/Hacks.cs diff --git a/Dalamud.CorePlugin/PluginImpl.cs b/Dalamud.CorePlugin/PluginImpl.cs index 5ed672f2d..03f11e989 100644 --- a/Dalamud.CorePlugin/PluginImpl.cs +++ b/Dalamud.CorePlugin/PluginImpl.cs @@ -2,6 +2,7 @@ using System; using System.IO; using Dalamud.Configuration.Internal; +using Dalamud.Game; using Dalamud.Game.Command; using Dalamud.Interface.Windowing; using Dalamud.Plugin; @@ -55,7 +56,7 @@ namespace Dalamud.CorePlugin /// /// Dalamud plugin interface. /// Logging service. - public PluginImpl(DalamudPluginInterface pluginInterface, IPluginLog log) + public PluginImpl(DalamudPluginInterface pluginInterface, IPluginLog log, ISigScanner scanner) { try { @@ -65,6 +66,8 @@ namespace Dalamud.CorePlugin this.windowSystem.AddWindow(new PluginWindow()); + this.pluginLog.Information(scanner.ToString()); + this.Interface.UiBuilder.Draw += this.OnDraw; this.Interface.UiBuilder.OpenConfigUi += this.OnOpenConfigUi; this.Interface.UiBuilder.OpenMainUi += this.OnOpenMainUi; diff --git a/Dalamud.Injector/Hacks.cs b/Dalamud.Injector/Hacks.cs new file mode 100644 index 000000000..7bc4468af --- /dev/null +++ b/Dalamud.Injector/Hacks.cs @@ -0,0 +1,20 @@ +using System; + +// ReSharper disable once CheckNamespace +namespace Dalamud; + +// TODO: Get rid of this! Move StartInfo to another assembly, make this good + +/// +/// Class to initialize Service<T>s. +/// +internal static class ServiceManager +{ + /// + /// Indicates that the class is a service. + /// + [AttributeUsage(AttributeTargets.Class)] + public class Service : Attribute + { + } +} diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 63494931c..1e9bc1523 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -19,6 +19,7 @@ namespace Dalamud.Configuration.Internal; /// Class containing Dalamud settings. /// [Serializable] +[ServiceManager.Service] internal sealed class DalamudConfiguration : IServiceType, IDisposable { private static readonly JsonSerializerSettings SerializerSettings = new() diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 2187f0da2..a9a3a511a 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -29,6 +29,7 @@ namespace Dalamud; /// /// The main Dalamud class containing all subsystems. /// +[ServiceManager.Service] internal sealed class Dalamud : IServiceType { #region Internals diff --git a/Dalamud/DalamudStartInfo.cs b/Dalamud/DalamudStartInfo.cs index 63a61c97e..f22388e9b 100644 --- a/Dalamud/DalamudStartInfo.cs +++ b/Dalamud/DalamudStartInfo.cs @@ -10,6 +10,7 @@ namespace Dalamud; /// Struct containing information needed to initialize Dalamud. /// [Serializable] +[ServiceManager.Service] public record DalamudStartInfo : IServiceType { /// diff --git a/Dalamud/Game/TargetSigScanner.cs b/Dalamud/Game/TargetSigScanner.cs index 0360f95cc..9242c5e83 100644 --- a/Dalamud/Game/TargetSigScanner.cs +++ b/Dalamud/Game/TargetSigScanner.cs @@ -11,6 +11,7 @@ namespace Dalamud.Game; /// [PluginInterface] [InterfaceVersion("1.0")] +[ServiceManager.Service] #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs index 3dd76473f..ce7ce25a1 100644 --- a/Dalamud/IoC/Internal/ServiceContainer.cs +++ b/Dalamud/IoC/Internal/ServiceContainer.cs @@ -16,6 +16,7 @@ namespace Dalamud.IoC.Internal; /// This is only used to resolve dependencies for plugins. /// Dalamud services are constructed via Service{T}.ConstructObject at the moment. /// +[ServiceManager.Service] internal class ServiceContainer : IServiceProvider, IServiceType { private static readonly ModuleLog Log = new("SERVICECONTAINER"); diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index 57e4ace10..bb680127c 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -92,28 +92,24 @@ internal static class ServiceManager var cacheDir = new DirectoryInfo(Path.Combine(startInfo.WorkingDirectory!, "cachedSigs")); if (!cacheDir.Exists) cacheDir.Create(); - + lock (LoadedServices) { - Service.Provide(dalamud); - LoadedServices.Add(typeof(Dalamud)); - - Service.Provide(startInfo); - LoadedServices.Add(typeof(DalamudStartInfo)); + void ProvideService(T service) where T : IServiceType + { + Debug.Assert(typeof(T).GetServiceKind().HasFlag(ServiceKind.ManualService), "Provided service must have Service attribute"); + Service.Provide(service); + LoadedServices.Add(typeof(T)); + } - Service.Provide(fs); - LoadedServices.Add(typeof(ReliableFileStorage)); - - Service.Provide(configuration); - LoadedServices.Add(typeof(DalamudConfiguration)); - - Service.Provide(new ServiceContainer()); - LoadedServices.Add(typeof(ServiceContainer)); - - Service.Provide( + ProvideService(dalamud); + ProvideService(startInfo); + ProvideService(fs); + ProvideService(configuration); + ProvideService(new ServiceContainer()); + ProvideService( new TargetSigScanner( - true, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}.json")))); - LoadedServices.Add(typeof(TargetSigScanner)); + true, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}.json")))); } using (Timings.Start("CS Resolver Init")) @@ -149,7 +145,8 @@ internal static class ServiceManager serviceContainer.RegisterInterfaces(serviceType); // Scoped service do not go through Service and are never early loaded - if (serviceKind.HasFlag(ServiceKind.ScopedService)) + // Manual services are provided + if (serviceKind.HasFlag(ServiceKind.ScopedService) || serviceKind.HasFlag(ServiceKind.ManualService)) continue; Debug.Assert( diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index 7fdd04880..6bc6cabcc 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -23,6 +23,7 @@ namespace Dalamud.Storage; /// /// This is not an early-loaded service, as it is needed before they are initialized. /// +[ServiceManager.Service] public class ReliableFileStorage : IServiceType, IDisposable { private static readonly ModuleLog Log = new("VFS"); From 6f99cfe48c288002cbdaebab8f29e585230faa0a Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 30 Sep 2023 01:17:27 +0200 Subject: [PATCH 111/120] fix: ScopedPluginLogService should be internal --- Dalamud/Logging/ScopedPluginLogService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Logging/ScopedPluginLogService.cs b/Dalamud/Logging/ScopedPluginLogService.cs index ca96fa64a..924b4885d 100644 --- a/Dalamud/Logging/ScopedPluginLogService.cs +++ b/Dalamud/Logging/ScopedPluginLogService.cs @@ -17,7 +17,7 @@ namespace Dalamud.Logging; #pragma warning disable SA1015 [ResolveVia] #pragma warning restore SA1015 -public class ScopedPluginLogService : IServiceType, IPluginLog, IDisposable +internal class ScopedPluginLogService : IServiceType, IPluginLog, IDisposable { private readonly LocalPlugin localPlugin; From f44c6794e77c701b46e1f47ec16586653856b521 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 30 Sep 2023 16:11:52 +0200 Subject: [PATCH 112/120] chore: tidy-up, move files shared between dalamud and injector into separate assembly --- Dalamud.Common/ClientLanguage.cs | 27 +++++++++++++ Dalamud.Common/Dalamud.Common.csproj | 13 +++++++ .../DalamudStartInfo.cs | 12 ++---- .../Game/GameVersion.cs | 18 ++++----- .../Game/GameVersionConverter.cs | 4 +- Dalamud.Injector/Dalamud.Injector.csproj | 8 +--- Dalamud.Injector/EntryPoint.cs | 3 +- Dalamud.Injector/Hacks.cs | 20 ---------- Dalamud.Test/Game/GameVersionTests.cs | 2 +- Dalamud.sln | 14 +++++++ Dalamud/ClientLanguage.cs | 2 + Dalamud/Dalamud.cs | 39 +++++++++++++++++-- Dalamud/Dalamud.csproj | 1 + Dalamud/Data/DataManager.cs | 28 +++++++------ Dalamud/EntryPoint.cs | 5 ++- Dalamud/Game/ChatHandlers.cs | 9 ++--- Dalamud/Game/ClientState/ClientState.cs | 4 +- Dalamud/Game/Command/CommandManager.cs | 6 +-- .../Interface/Internal/DalamudInterface.cs | 12 +++--- .../Interface/Internal/InterfaceManager.cs | 4 +- Dalamud/Interface/Internal/TextureManager.cs | 12 +++--- .../Internal/Windows/BranchSwitcherWindow.cs | 2 +- .../Windows/Data/Widgets/StartInfoWidget.cs | 2 +- .../PluginInstaller/PluginInstallerWindow.cs | 7 ++-- Dalamud/Plugin/Internal/PluginManager.cs | 12 +++--- Dalamud/Plugin/Internal/Types/LocalPlugin.cs | 8 ++-- .../Plugin/Internal/Types/PluginManifest.cs | 3 +- Dalamud/ServiceManager.cs | 22 ++--------- Dalamud/Support/Troubleshooting.cs | 4 +- 29 files changed, 174 insertions(+), 129 deletions(-) create mode 100644 Dalamud.Common/ClientLanguage.cs create mode 100644 Dalamud.Common/Dalamud.Common.csproj rename {Dalamud => Dalamud.Common}/DalamudStartInfo.cs (96%) rename {Dalamud => Dalamud.Common}/Game/GameVersion.cs (97%) rename {Dalamud => Dalamud.Common}/Game/GameVersionConverter.cs (98%) delete mode 100644 Dalamud.Injector/Hacks.cs diff --git a/Dalamud.Common/ClientLanguage.cs b/Dalamud.Common/ClientLanguage.cs new file mode 100644 index 000000000..1fd58dce1 --- /dev/null +++ b/Dalamud.Common/ClientLanguage.cs @@ -0,0 +1,27 @@ +namespace Dalamud.Common; + +/// +/// Enum describing the language the game loads in. +/// +public enum ClientLanguage +{ + /// + /// Indicating a Japanese game client. + /// + Japanese, + + /// + /// Indicating an English game client. + /// + English, + + /// + /// Indicating a German game client. + /// + German, + + /// + /// Indicating a French game client. + /// + French, +} diff --git a/Dalamud.Common/Dalamud.Common.csproj b/Dalamud.Common/Dalamud.Common.csproj new file mode 100644 index 000000000..ac5d3fdba --- /dev/null +++ b/Dalamud.Common/Dalamud.Common.csproj @@ -0,0 +1,13 @@ + + + + net7.0 + enable + enable + + + + + + + diff --git a/Dalamud/DalamudStartInfo.cs b/Dalamud.Common/DalamudStartInfo.cs similarity index 96% rename from Dalamud/DalamudStartInfo.cs rename to Dalamud.Common/DalamudStartInfo.cs index f22388e9b..069a0ef9f 100644 --- a/Dalamud/DalamudStartInfo.cs +++ b/Dalamud.Common/DalamudStartInfo.cs @@ -1,17 +1,13 @@ -using System; -using System.Collections.Generic; - -using Dalamud.Game; +using Dalamud.Common.Game; using Newtonsoft.Json; -namespace Dalamud; +namespace Dalamud.Common; /// /// Struct containing information needed to initialize Dalamud. /// [Serializable] -[ServiceManager.Service] -public record DalamudStartInfo : IServiceType +public record DalamudStartInfo { /// /// Initializes a new instance of the class. @@ -97,7 +93,7 @@ public record DalamudStartInfo : IServiceType /// /// Gets or sets troubleshooting information to attach when generating a tspack file. /// - public string TroubleshootingPackData { get; set; } + public string? TroubleshootingPackData { get; set; } /// /// Gets or sets a value that specifies how much to wait before a new Dalamud session. diff --git a/Dalamud/Game/GameVersion.cs b/Dalamud.Common/Game/GameVersion.cs similarity index 97% rename from Dalamud/Game/GameVersion.cs rename to Dalamud.Common/Game/GameVersion.cs index 2b2021e60..26ff0e48f 100644 --- a/Dalamud/Game/GameVersion.cs +++ b/Dalamud.Common/Game/GameVersion.cs @@ -1,11 +1,9 @@ -using System; using System.Globalization; -using System.Linq; using System.Text; using Newtonsoft.Json; -namespace Dalamud.Game; +namespace Dalamud.Common.Game; /// /// A GameVersion object contains give hierarchical numeric components: year, month, @@ -168,14 +166,14 @@ public sealed class GameVersion : ICloneable, IComparable, IComparable new GameVersion(this.Year, this.Month, this.Day, this.Major, this.Minor); /// - public int CompareTo(object obj) + public int CompareTo(object? obj) { if (obj == null) return 1; @@ -315,7 +313,7 @@ public sealed class GameVersion : ICloneable, IComparable, IComparable - public int CompareTo(GameVersion value) + public int CompareTo(GameVersion? value) { if (value == null) return 1; @@ -348,7 +346,7 @@ public sealed class GameVersion : ICloneable, IComparable, IComparable - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not GameVersion value) return false; @@ -357,7 +355,7 @@ public sealed class GameVersion : ICloneable, IComparable, IComparable - public bool Equals(GameVersion value) + public bool Equals(GameVersion? value) { if (value == null) { diff --git a/Dalamud/Game/GameVersionConverter.cs b/Dalamud.Common/Game/GameVersionConverter.cs similarity index 98% rename from Dalamud/Game/GameVersionConverter.cs rename to Dalamud.Common/Game/GameVersionConverter.cs index f307b6fb9..a1876869a 100644 --- a/Dalamud/Game/GameVersionConverter.cs +++ b/Dalamud.Common/Game/GameVersionConverter.cs @@ -1,8 +1,6 @@ -using System; - using Newtonsoft.Json; -namespace Dalamud.Game; +namespace Dalamud.Common.Game; /// /// Converts a to and from a string (e.g. "2010.01.01.1234.5678"). diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj index ea9e4f0a3..d8a74e58d 100644 --- a/Dalamud.Injector/Dalamud.Injector.csproj +++ b/Dalamud.Injector/Dalamud.Injector.csproj @@ -81,12 +81,6 @@ - - - - - - - + diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs index a35248062..bd9fa87f8 100644 --- a/Dalamud.Injector/EntryPoint.cs +++ b/Dalamud.Injector/EntryPoint.cs @@ -9,7 +9,8 @@ using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; -using Dalamud.Game; +using Dalamud.Common; +using Dalamud.Common.Game; using Newtonsoft.Json; using Reloaded.Memory.Buffers; using Serilog; diff --git a/Dalamud.Injector/Hacks.cs b/Dalamud.Injector/Hacks.cs deleted file mode 100644 index 7bc4468af..000000000 --- a/Dalamud.Injector/Hacks.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; - -// ReSharper disable once CheckNamespace -namespace Dalamud; - -// TODO: Get rid of this! Move StartInfo to another assembly, make this good - -/// -/// Class to initialize Service<T>s. -/// -internal static class ServiceManager -{ - /// - /// Indicates that the class is a service. - /// - [AttributeUsage(AttributeTargets.Class)] - public class Service : Attribute - { - } -} diff --git a/Dalamud.Test/Game/GameVersionTests.cs b/Dalamud.Test/Game/GameVersionTests.cs index 44a5813c8..dcace4279 100644 --- a/Dalamud.Test/Game/GameVersionTests.cs +++ b/Dalamud.Test/Game/GameVersionTests.cs @@ -1,4 +1,4 @@ -using Dalamud.Game; +using Dalamud.Common.Game; using Xunit; namespace Dalamud.Test.Game diff --git a/Dalamud.sln b/Dalamud.sln index 443f38496..200238a83 100644 --- a/Dalamud.sln +++ b/Dalamud.sln @@ -38,6 +38,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFXIVClientStructs.InteropS EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DalamudCrashHandler", "DalamudCrashHandler\DalamudCrashHandler.vcxproj", "{317A264C-920B-44A1-8A34-F3A6827B0705}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Common", "Dalamud.Common\Dalamud.Common.csproj", "{F21B13D2-D7D0-4456-B70F-3F8D695064E2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -202,6 +204,18 @@ Global {317A264C-920B-44A1-8A34-F3A6827B0705}.Release|x64.Build.0 = Release|x64 {317A264C-920B-44A1-8A34-F3A6827B0705}.Release|x86.ActiveCfg = Release|x64 {317A264C-920B-44A1-8A34-F3A6827B0705}.Release|x86.Build.0 = Release|x64 + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Debug|x64.ActiveCfg = Debug|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Debug|x64.Build.0 = Debug|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Debug|x86.ActiveCfg = Debug|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Debug|x86.Build.0 = Debug|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Release|Any CPU.Build.0 = Release|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Release|x64.ActiveCfg = Release|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Release|x64.Build.0 = Release|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Release|x86.ActiveCfg = Release|Any CPU + {F21B13D2-D7D0-4456-B70F-3F8D695064E2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Dalamud/ClientLanguage.cs b/Dalamud/ClientLanguage.cs index 4e04d4a54..8f2c52456 100644 --- a/Dalamud/ClientLanguage.cs +++ b/Dalamud/ClientLanguage.cs @@ -1,5 +1,7 @@ namespace Dalamud; +// TODO(v10): Delete this, and use Dalamud.Common.ClientLanguage instead for everything. + /// /// Enum describing the language the game loads in. /// diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index a9a3a511a..8a75049ad 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.IO; using System.Linq; @@ -7,6 +6,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using Dalamud.Common; using Dalamud.Configuration.Internal; using Dalamud.Game; using Dalamud.Game.Gui.Internal; @@ -14,6 +14,7 @@ using Dalamud.Interface.Internal; using Dalamud.Plugin.Internal; using Dalamud.Storage; using Dalamud.Utility; +using Dalamud.Utility.Timing; using PInvoke; using Serilog; @@ -47,10 +48,28 @@ internal sealed class Dalamud : IServiceType /// Event used to signal the main thread to continue. public Dalamud(DalamudStartInfo info, ReliableFileStorage fs, DalamudConfiguration configuration, IntPtr mainThreadContinueEvent) { + this.StartInfo = info; + this.unloadSignal = new ManualResetEvent(false); this.unloadSignal.Reset(); + + // Directory resolved signatures(CS, our own) will be cached in + var cacheDir = new DirectoryInfo(Path.Combine(this.StartInfo.WorkingDirectory!, "cachedSigs")); + if (!cacheDir.Exists) + cacheDir.Create(); + + // Set up the SigScanner for our target module + TargetSigScanner scanner; + using (Timings.Start("SigScanner Init")) + { + scanner = new TargetSigScanner( + true, new FileInfo(Path.Combine(cacheDir.FullName, $"{this.StartInfo.GameVersion}.json"))); + } - ServiceManager.InitializeProvidedServicesAndClientStructs(this, info, fs, configuration); + ServiceManager.InitializeProvidedServices(this, fs, configuration, scanner); + + // Set up FFXIVClientStructs + this.SetupClientStructsResolver(cacheDir); if (!configuration.IsResumeGameAfterPluginLoad) { @@ -97,11 +116,16 @@ internal sealed class Dalamud : IServiceType }); } } + + /// + /// Gets the start information for this Dalamud instance. + /// + internal DalamudStartInfo StartInfo { get; private set; } /// /// Gets location of stored assets. /// - internal DirectoryInfo AssetDirectory => new(Service.Get().AssetDirectory!); + internal DirectoryInfo AssetDirectory => new(this.StartInfo.AssetDirectory!); /// /// Signal to the crash handler process that we should restart the game. @@ -176,4 +200,13 @@ internal sealed class Dalamud : IServiceType var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(releaseFilter); Log.Debug("Reset ExceptionFilter, old: {0}", oldFilter); } + + private void SetupClientStructsResolver(DirectoryInfo cacheDir) + { + using (Timings.Start("CS Resolver Init")) + { + FFXIVClientStructs.Interop.Resolver.GetInstance.SetupSearchSpace(Service.Get().SearchBase, new FileInfo(Path.Combine(cacheDir.FullName, $"{this.StartInfo.GameVersion}_cs.json"))); + FFXIVClientStructs.Interop.Resolver.GetInstance.Resolve(); + } + } } diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 7ae97e1a6..69d08f517 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -89,6 +89,7 @@ + diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index f1f98229a..6195532ab 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -7,6 +7,7 @@ using System.Threading; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Services; +using Dalamud.Utility; using Dalamud.Utility.Timing; using JetBrains.Annotations; using Lumina; @@ -32,9 +33,9 @@ internal sealed class DataManager : IDisposable, IServiceType, IDataManager private readonly CancellationTokenSource luminaCancellationTokenSource; [ServiceManager.ServiceConstructor] - private DataManager(DalamudStartInfo dalamudStartInfo, Dalamud dalamud) + private DataManager(Dalamud dalamud) { - this.Language = dalamudStartInfo.Language; + this.Language = (ClientLanguage)dalamud.StartInfo.Language; // Set up default values so plugins do not null-reference when data is being loaded. this.ClientOpCodes = this.ServerOpCodes = new ReadOnlyDictionary(new Dictionary()); @@ -82,17 +83,20 @@ internal sealed class DataManager : IDisposable, IServiceType, IDataManager Log.Information("Lumina is ready: {0}", this.GameData.DataPath); - try + if (!dalamud.StartInfo.TroubleshootingPackData.IsNullOrEmpty()) { - var tsInfo = - JsonConvert.DeserializeObject( - dalamudStartInfo.TroubleshootingPackData); - this.HasModifiedGameDataFiles = - tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception; - } - catch - { - // ignored + try + { + var tsInfo = + JsonConvert.DeserializeObject( + dalamud.StartInfo.TroubleshootingPackData); + this.HasModifiedGameDataFiles = + tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception; + } + catch + { + // ignored + } } } diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 6b53ee3a6..c9537eda6 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.IO; using System.Net; @@ -6,6 +5,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using Dalamud.Common; using Dalamud.Configuration.Internal; using Dalamud.Logging.Internal; using Dalamud.Logging.Retention; @@ -163,6 +163,9 @@ public sealed class EntryPoint Log.Information(new string('-', 80)); Log.Information("Initializing a session.."); + if (string.IsNullOrEmpty(info.WorkingDirectory)) + throw new Exception("Working directory was invalid"); + Reloaded.Hooks.Tools.Utilities.FasmBasePath = new DirectoryInfo(info.WorkingDirectory); // This is due to GitHub not supporting TLS 1.0, so we enable all TLS versions globally diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index 896d296fc..d2f4b30c7 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -14,8 +13,6 @@ using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Interface.Internal; using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Internal.Windows; -using Dalamud.IoC; -using Dalamud.IoC.Internal; using Dalamud.Plugin.Internal; using Dalamud.Utility; using Serilog; @@ -104,6 +101,9 @@ internal class ChatHandlers : IServiceType private readonly DalamudLinkPayload openInstallerWindowLink; + [ServiceManager.ServiceDependency] + private readonly Dalamud dalamud = Service.Get(); + [ServiceManager.ServiceDependency] private readonly DalamudConfiguration configuration = Service.Get(); @@ -160,7 +160,6 @@ internal class ChatHandlers : IServiceType private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { - var startInfo = Service.Get(); var clientState = Service.GetNullable(); if (clientState == null) return; @@ -182,7 +181,7 @@ internal class ChatHandlers : IServiceType if (type == XivChatType.RetainerSale) { - foreach (var regex in this.retainerSaleRegexes[startInfo.Language]) + foreach (var regex in this.retainerSaleRegexes[(ClientLanguage)this.dalamud.StartInfo.Language]) { var matchInfo = regex.Match(message.TextValue); diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index ccb87ff0e..3b3f65128 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -41,7 +41,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState private bool lastFramePvP; [ServiceManager.ServiceConstructor] - private ClientState(TargetSigScanner sigScanner, DalamudStartInfo startInfo, GameLifecycle lifecycle) + private ClientState(TargetSigScanner sigScanner, Dalamud dalamud, GameLifecycle lifecycle) { this.lifecycle = lifecycle; this.address = new ClientStateAddressResolver(); @@ -49,7 +49,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState Log.Verbose("===== C L I E N T S T A T E ====="); - this.ClientLanguage = startInfo.Language; + this.ClientLanguage = (ClientLanguage)dalamud.StartInfo.Language; Log.Verbose($"SetupTerritoryType address 0x{this.address.SetupTerritoryType.ToInt64():X}"); diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs index 218b89676..6b67f1892 100644 --- a/Dalamud/Game/Command/CommandManager.cs +++ b/Dalamud/Game/Command/CommandManager.cs @@ -35,15 +35,15 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage private readonly ChatGui chatGui = Service.Get(); [ServiceManager.ServiceConstructor] - private CommandManager(DalamudStartInfo startInfo) + private CommandManager(Dalamud dalamud) { - this.currentLangCommandRegex = startInfo.Language switch + this.currentLangCommandRegex = (ClientLanguage)dalamud.StartInfo.Language switch { ClientLanguage.Japanese => this.commandRegexJp, ClientLanguage.English => this.commandRegexEn, ClientLanguage.German => this.commandRegexDe, ClientLanguage.French => this.commandRegexFr, - _ => this.currentLangCommandRegex, + _ => this.commandRegexEn, }; this.chatGui.CheckMessageHandled += this.OnCheckMessageHandled; diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index cfaae485a..9e4c215b3 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -635,9 +635,7 @@ internal class DalamudInterface : IDisposable, IServiceType ImGui.EndMenu(); } - - var startInfo = Service.Get(); - + var logSynchronously = configuration.LogSynchronously; if (ImGui.MenuItem("Log Synchronously", null, ref logSynchronously)) { @@ -645,10 +643,10 @@ internal class DalamudInterface : IDisposable, IServiceType configuration.QueueSave(); EntryPoint.InitLogging( - startInfo.LogPath!, - startInfo.BootShowConsole, + dalamud.StartInfo.LogPath!, + dalamud.StartInfo.BootShowConsole, configuration.LogSynchronously, - startInfo.LogName); + dalamud.StartInfo.LogName); } var antiDebug = Service.Get(); @@ -767,7 +765,7 @@ internal class DalamudInterface : IDisposable, IServiceType } ImGui.MenuItem(Util.AssemblyVersion, false); - ImGui.MenuItem(startInfo.GameVersion?.ToString() ?? "Unknown version", false); + ImGui.MenuItem(dalamud.StartInfo.GameVersion?.ToString() ?? "Unknown version", false); ImGui.MenuItem($"D: {Util.GetGitHash()}[{Util.GetGitCommitCount()}] CS: {Util.GetGitHashClientStructs()}[{FFXIVClientStructs.Interop.Resolver.Version}]", false); ImGui.MenuItem($"CLR: {Environment.Version}", false); diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index d00f33180..dd85f1db4 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -563,10 +563,10 @@ internal class InterfaceManager : IDisposable, IServiceType return; } - var startInfo = Service.Get(); + var startInfo = Service.Get().StartInfo; var configuration = Service.Get(); - var iniFileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(startInfo.ConfigurationPath), "dalamudUI.ini")); + var iniFileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(startInfo.ConfigurationPath)!, "dalamudUI.ini")); try { diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 7c773bd36..9fecf74f4 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -39,7 +39,8 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe private readonly Framework framework; private readonly DataManager dataManager; private readonly InterfaceManager im; - private readonly DalamudStartInfo startInfo; + + private readonly ClientLanguage language; private readonly Dictionary activeTextures = new(); @@ -48,17 +49,18 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe /// /// Initializes a new instance of the class. /// + /// Dalamud instance. /// Framework instance. /// DataManager instance. /// InterfaceManager instance. - /// DalamudStartInfo instance. [ServiceManager.ServiceConstructor] - public TextureManager(Framework framework, DataManager dataManager, InterfaceManager im, DalamudStartInfo startInfo) + public TextureManager(Dalamud dalamud, Framework framework, DataManager dataManager, InterfaceManager im) { this.framework = framework; this.dataManager = dataManager; this.im = im; - this.startInfo = startInfo; + + this.language = (ClientLanguage)dalamud.StartInfo.Language; this.framework.Update += this.FrameworkOnUpdate; @@ -115,7 +117,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe if (this.dataManager.FileExists(path)) return path; - language ??= this.startInfo.Language; + language ??= this.language; var languageFolder = language switch { ClientLanguage.Japanese => "ja/", diff --git a/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs b/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs index 05d8d04e8..dcde7d008 100644 --- a/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs +++ b/Dalamud/Interface/Internal/Windows/BranchSwitcherWindow.cs @@ -66,7 +66,7 @@ public class BranchSwitcherWindow : Window return; } - var si = Service.Get(); + var si = Service.Get().StartInfo; var itemsArray = this.branches.Select(x => x.Key).ToArray(); ImGui.ListBox("Branch", ref this.selectedBranchIndex, itemsArray, itemsArray.Length); diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs index 65ed65e03..4dee316c5 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/StartInfoWidget.cs @@ -26,7 +26,7 @@ internal class StartInfoWidget : IDataWindowWidget /// public void Draw() { - var startInfo = Service.Get(); + var startInfo = Service.Get().StartInfo; ImGui.Text(JsonConvert.SerializeObject(startInfo, Formatting.Indented)); } diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 6e2ad862c..7ff2f61e0 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -1994,7 +1994,6 @@ internal class PluginInstallerWindow : Window, IDisposable { var configuration = Service.Get(); var pluginManager = Service.Get(); - var startInfo = Service.Get(); if (ImGui.BeginPopupContextItem("ItemContextMenu")) { @@ -2022,10 +2021,10 @@ internal class PluginInstallerWindow : Window, IDisposable Task.Run(() => { pluginManager.PluginConfigs.Delete(manifest.InternalName); + var dir = pluginManager.PluginConfigs.GetDirectory(manifest.InternalName); - var path = Path.Combine(startInfo.PluginDirectory, manifest.InternalName); - if (Directory.Exists(path)) - Directory.Delete(path, true); + if (Directory.Exists(dir)) + Directory.Delete(dir, true); }) .ContinueWith(task => { diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 49608ac9b..dc658792c 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -74,7 +74,7 @@ internal partial class PluginManager : IDisposable, IServiceType private readonly DalamudConfiguration configuration = Service.Get(); [ServiceManager.ServiceDependency] - private readonly DalamudStartInfo startInfo = Service.Get(); + private readonly Dalamud dalamud = Service.Get(); [ServiceManager.ServiceDependency] private readonly ProfileManager profileManager = Service.Get(); @@ -90,12 +90,12 @@ internal partial class PluginManager : IDisposable, IServiceType [ServiceManager.ServiceConstructor] private PluginManager() { - this.pluginDirectory = new DirectoryInfo(this.startInfo.PluginDirectory!); + this.pluginDirectory = new DirectoryInfo(this.dalamud.StartInfo.PluginDirectory!); if (!this.pluginDirectory.Exists) this.pluginDirectory.Create(); - this.SafeMode = EnvironmentConfiguration.DalamudNoPlugins || this.configuration.PluginSafeMode || this.startInfo.NoLoadPlugins; + this.SafeMode = EnvironmentConfiguration.DalamudNoPlugins || this.configuration.PluginSafeMode || this.dalamud.StartInfo.NoLoadPlugins; try { @@ -119,9 +119,9 @@ internal partial class PluginManager : IDisposable, IServiceType this.configuration.QueueSave(); } - this.PluginConfigs = new PluginConfigurations(Path.Combine(Path.GetDirectoryName(this.startInfo.ConfigurationPath) ?? string.Empty, "pluginConfigs")); + this.PluginConfigs = new PluginConfigurations(Path.Combine(Path.GetDirectoryName(this.dalamud.StartInfo.ConfigurationPath) ?? string.Empty, "pluginConfigs")); - var bannedPluginsJson = File.ReadAllText(Path.Combine(this.startInfo.AssetDirectory!, "UIRes", "bannedplugin.json")); + var bannedPluginsJson = File.ReadAllText(Path.Combine(this.dalamud.StartInfo.AssetDirectory!, "UIRes", "bannedplugin.json")); this.bannedPlugins = JsonConvert.DeserializeObject(bannedPluginsJson); if (this.bannedPlugins == null) { @@ -1168,7 +1168,7 @@ internal partial class PluginManager : IDisposable, IServiceType } // Applicable version - if (manifest.ApplicableVersion < this.startInfo.GameVersion) + if (manifest.ApplicableVersion < this.dalamud.StartInfo.GameVersion) { Log.Verbose($"Game version: {manifest.InternalName} - {manifest.AssemblyVersion} - {manifest.TestingAssemblyVersion}"); return false; diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index 80d6edfd3..57bea0f57 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -1,10 +1,10 @@ -using System; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Dalamud.Common.Game; using Dalamud.Configuration.Internal; using Dalamud.Game; using Dalamud.Game.Gui.Dtr; @@ -336,7 +336,7 @@ internal class LocalPlugin : IDisposable var framework = await Service.GetAsync(); var ioc = await Service.GetAsync(); var pluginManager = await Service.GetAsync(); - var startInfo = await Service.GetAsync(); + var dalamud = await Service.GetAsync(); // UiBuilder constructor requires the following two. await Service.GetAsync(); @@ -392,7 +392,7 @@ internal class LocalPlugin : IDisposable if (pluginManager.IsManifestBanned(this.manifest) && !this.IsDev) throw new BannedPluginException($"Unable to load {this.Name}, banned"); - if (this.manifest.ApplicableVersion < startInfo.GameVersion) + if (this.manifest.ApplicableVersion < dalamud.StartInfo.GameVersion) throw new InvalidPluginOperationException($"Unable to load {this.Name}, no applicable version"); if (this.manifest.DalamudApiLevel < PluginManager.DalamudApiLevel && !pluginManager.LoadAllApiLevels) @@ -624,7 +624,7 @@ internal class LocalPlugin : IDisposable /// Whether or not this plugin shouldn't load. public bool CheckPolicy() { - var startInfo = Service.Get(); + var startInfo = Service.Get().StartInfo; var manager = Service.Get(); if (startInfo.NoLoadPlugins) diff --git a/Dalamud/Plugin/Internal/Types/PluginManifest.cs b/Dalamud/Plugin/Internal/Types/PluginManifest.cs index 0b5ec26fc..34fa04f6e 100644 --- a/Dalamud/Plugin/Internal/Types/PluginManifest.cs +++ b/Dalamud/Plugin/Internal/Types/PluginManifest.cs @@ -1,7 +1,6 @@ -using System; using System.Collections.Generic; -using Dalamud.Game; +using Dalamud.Common.Game; using Dalamud.Plugin.Internal.Types.Manifest; using Newtonsoft.Json; diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index bb680127c..e8512e854 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -1,7 +1,5 @@ -using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Reflection; using System.Threading; @@ -83,16 +81,11 @@ internal static class ServiceManager /// Initializes Provided Services and FFXIVClientStructs. /// /// Instance of . - /// Instance of . /// Instance of . /// Instance of . - public static void InitializeProvidedServicesAndClientStructs(Dalamud dalamud, DalamudStartInfo startInfo, ReliableFileStorage fs, DalamudConfiguration configuration) + /// Instance of . + public static void InitializeProvidedServices(Dalamud dalamud, ReliableFileStorage fs, DalamudConfiguration configuration, TargetSigScanner scanner) { - // Initialize the process information. - var cacheDir = new DirectoryInfo(Path.Combine(startInfo.WorkingDirectory!, "cachedSigs")); - if (!cacheDir.Exists) - cacheDir.Create(); - lock (LoadedServices) { void ProvideService(T service) where T : IServiceType @@ -103,19 +96,10 @@ internal static class ServiceManager } ProvideService(dalamud); - ProvideService(startInfo); ProvideService(fs); ProvideService(configuration); ProvideService(new ServiceContainer()); - ProvideService( - new TargetSigScanner( - true, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}.json")))); - } - - using (Timings.Start("CS Resolver Init")) - { - FFXIVClientStructs.Interop.Resolver.GetInstance.SetupSearchSpace(Service.Get().SearchBase, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}_cs.json"))); - FFXIVClientStructs.Interop.Resolver.GetInstance.Resolve(); + ProvideService(scanner); } } diff --git a/Dalamud/Support/Troubleshooting.cs b/Dalamud/Support/Troubleshooting.cs index 9893451f4..59ebcaa16 100644 --- a/Dalamud/Support/Troubleshooting.cs +++ b/Dalamud/Support/Troubleshooting.cs @@ -58,7 +58,7 @@ public static class Troubleshooting /// internal static void LogTroubleshooting() { - var startInfo = Service.Get(); + var startInfo = Service.Get().StartInfo; var configuration = Service.Get(); var interfaceManager = Service.GetNullable(); var pluginManager = Service.GetNullable(); @@ -72,7 +72,7 @@ public static class Troubleshooting EverStartedLoadingPlugins = pluginManager?.InstalledPlugins.Where(x => x.HasEverStartedLoad).Select(x => x.InternalName).ToList(), DalamudVersion = Util.AssemblyVersion, DalamudGitHash = Util.GetGitHash(), - GameVersion = startInfo.GameVersion.ToString(), + GameVersion = startInfo.GameVersion?.ToString() ?? "Unknown", Language = startInfo.Language.ToString(), BetaKey = configuration.DalamudBetaKey, DoPluginTest = configuration.DoPluginTest, From 55ab59a76be12ceb364e8ad27d5a908e5a0c595d Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sat, 30 Sep 2023 16:34:02 +0200 Subject: [PATCH 113/120] Update ClientStructs --- lib/FFXIVClientStructs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index a1ddff097..bfcc02f0b 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit a1ddff0974729a2e984d8cc1dc007eff19bd74ab +Subproject commit bfcc02f0ba0fa0ee14603ee6b6f385eaeebbe43c From 8fde0af0f976a230004e1dde37173aefe3d045b8 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 30 Sep 2023 18:25:17 -0700 Subject: [PATCH 114/120] Add IconBrowser Widget --- .../Internal/Windows/Data/DataWindow.cs | 2 +- .../Windows/Data/Widgets/IconBrowserWidget.cs | 216 ++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs diff --git a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs index 1363c6abe..ba47d2c8e 100644 --- a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs +++ b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Numerics; @@ -50,6 +49,7 @@ internal class DataWindow : Window new UIColorWidget(), new DataShareWidget(), new NetworkMonitorWidget(), + new IconBrowserWidget(), }; private readonly IOrderedEnumerable orderedModules; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs new file mode 100644 index 000000000..b37878045 --- /dev/null +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs @@ -0,0 +1,216 @@ +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Numerics; + +using Dalamud.Data; +using Dalamud.Interface.Utility; +using Dalamud.Utility; +using ImGuiNET; + +namespace Dalamud.Interface.Internal.Windows.Data.Widgets; + +/// +/// Data widget for browsing in-game icons. +/// +public class IconBrowserWidget : IDataWindowWidget +{ + // Remove range 170,000 -> 180,000 by default, this specific range causes exceptions. + private readonly HashSet nullValues = Enumerable.Range(170000, 10000).ToHashSet(); + + private Vector2 iconSize = new(64.0f, 64.0f); + private Vector2 editIconSize = new(64.0f, 64.0f); + + private List valueRange = Enumerable.Range(0, 200000).ToList(); + + private int lastNullValueCount; + private int startRange; + private int stopRange = 200000; + private bool showTooltipImage; + + private Vector2 mouseDragStart; + private bool dragStarted; + private Vector2 lastWindowSize = Vector2.Zero; + + /// + public string[]? CommandShortcuts { get; init; } = { "icon", "icons" }; + + /// + public string DisplayName { get; init; } = "Icon Browser"; + + /// + public bool Ready { get; set; } = true; + + /// + public void Load() + { + } + + /// + public void Draw() + { + this.DrawOptions(); + + if (ImGui.BeginChild("ScrollableSection", ImGui.GetContentRegionAvail(), false, ImGuiWindowFlags.NoMove)) + { + var itemsPerRow = (int)MathF.Floor(ImGui.GetContentRegionMax().X / (this.iconSize.X + ImGui.GetStyle().ItemSpacing.X)); + var itemHeight = this.iconSize.Y + ImGui.GetStyle().ItemSpacing.Y; + + ImGuiClip.ClippedDraw(this.valueRange, this.DrawIcon, itemsPerRow, itemHeight); + } + + ImGui.EndChild(); + + this.ProcessMouseDragging(); + + if (this.lastNullValueCount != this.nullValues.Count) + { + this.RecalculateIndexRange(); + this.lastNullValueCount = this.nullValues.Count; + } + } + + // Limit the popup image to half our screen size. + private static float GetImageScaleFactor(IDalamudTextureWrap texture) + { + var workArea = ImGui.GetMainViewport().Size / 2.0f; + var scale = 1.0f; + + if (texture.Width > workArea.X || texture.Height > workArea.Y) + { + var widthRatio = workArea.X / texture.Width; + var heightRatio = workArea.Y / texture.Height; + + scale = MathF.Min(widthRatio, heightRatio); + } + + return scale; + } + + private void DrawOptions() + { + ImGui.Columns(2); + + ImGui.PushItemWidth(ImGui.GetContentRegionAvail().X); + if (ImGui.InputInt("##StartRange", ref this.startRange, 0, 0)) this.RecalculateIndexRange(); + + ImGui.NextColumn(); + ImGui.PushItemWidth(ImGui.GetContentRegionAvail().X); + if (ImGui.InputInt("##StopRange", ref this.stopRange, 0, 0)) this.RecalculateIndexRange(); + + ImGui.NextColumn(); + ImGui.Checkbox("Show Image in Tooltip", ref this.showTooltipImage); + + ImGui.NextColumn(); + ImGui.InputFloat2("Icon Size", ref this.editIconSize); + if (ImGui.IsItemDeactivatedAfterEdit()) + { + this.iconSize = this.editIconSize; + } + + ImGui.Columns(1); + } + + private void DrawIcon(int iconId) + { + try + { + var cursor = ImGui.GetCursorScreenPos(); + + if (!this.IsIconValid(iconId)) + { + this.nullValues.Add(iconId); + return; + } + + if (Service.Get().GetIcon((uint)iconId) is { } texture) + { + ImGui.Image(texture.ImGuiHandle, this.iconSize); + + // If we have the option to show a tooltip image, draw the image, but make sure it's not too big. + if (ImGui.IsItemHovered() && this.showTooltipImage) + { + ImGui.BeginTooltip(); + + var scale = GetImageScaleFactor(texture); + + var textSize = ImGui.CalcTextSize(iconId.ToString()); + ImGui.SetCursorPosX(texture.Size.X * scale / 2.0f - textSize.X / 2.0f + ImGui.GetStyle().FramePadding.X * 2.0f); + ImGui.Text(iconId.ToString()); + + ImGui.Image(texture.ImGuiHandle, texture.Size * scale); + ImGui.EndTooltip(); + } + + // else, just draw the iconId. + else if (ImGui.IsItemHovered()) + { + ImGui.SetTooltip(iconId.ToString()); + } + } + else + { + // This texture was null, draw nothing, and prevent from trying to show it again. + this.nullValues.Add(iconId); + } + + ImGui.GetWindowDrawList().AddRect(cursor, cursor + this.iconSize, ImGui.GetColorU32(KnownColor.White.Vector())); + } + catch (Exception) + { + // If something went wrong, prevent from trying to show this icon again. + this.nullValues.Add(iconId); + } + } + + private void ProcessMouseDragging() + { + if (ImGui.IsItemHovered() || this.dragStarted) + { + if (ImGui.GetWindowSize() == this.lastWindowSize) + { + if (ImGui.IsItemClicked(ImGuiMouseButton.Left) && !this.dragStarted) + { + this.mouseDragStart = ImGui.GetMousePos(); + this.dragStarted = true; + } + } + else + { + this.lastWindowSize = ImGui.GetWindowSize(); + this.dragStarted = false; + } + } + + if (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && this.dragStarted) + { + var delta = this.mouseDragStart - ImGui.GetMousePos(); + ImGui.GetIO().AddMouseWheelEvent(0.0f, -delta.Y / 85.0f); + this.mouseDragStart = ImGui.GetMousePos(); + } + else if (ImGui.IsMouseReleased(ImGuiMouseButton.Left)) + { + this.dragStarted = false; + } + } + + // Check if the icon has a valid filepath, and exists in the game data. + private bool IsIconValid(int iconId) + { + var filePath = Service.Get().GetIconPath((uint)iconId); + return !filePath.IsNullOrEmpty() && Service.Get().FileExists(filePath); + } + + private void RecalculateIndexRange() + { + if (this.stopRange <= this.startRange || this.stopRange <= 0 || this.startRange < 0) + { + this.valueRange = new List(); + } + else + { + this.valueRange = Enumerable.Range(this.startRange, this.stopRange - this.startRange).ToList(); + this.valueRange.RemoveAll(value => this.nullValues.Contains(value)); + } + } +} From 6e8a97336c9ba870c779b52ec8c36010a006f963 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 1 Oct 2023 12:58:31 +0200 Subject: [PATCH 115/120] fix: remove invalid assert in TextureManager --- Dalamud/Interface/Internal/TextureManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index 9fecf74f4..40aa72913 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -297,10 +297,9 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe TextureInfo? info; lock (this.activeTextures) { + // This either is a new texture, or it had been evicted and now wants to be drawn again. if (!this.activeTextures.TryGetValue(path, out info)) { - Debug.Assert(rethrow, "This should never run when getting outside of creator"); - info = new TextureInfo(); this.activeTextures.Add(path, info); } From 0690f5dd2ab23f8c356b76ca19d6a1179a7c2eff Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 1 Oct 2023 16:40:48 +0200 Subject: [PATCH 116/120] fix: always use frame height to draw icon buttons --- .../Components/ImGuiComponents.IconButton.cs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs b/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs index 1c484d423..116b04bd2 100644 --- a/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs +++ b/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs @@ -110,11 +110,32 @@ public static partial class ImGuiComponents numColors++; } + var icon = iconText; + if (icon.Contains("#")) + icon = icon[..icon.IndexOf("#", StringComparison.Ordinal)]; + + ImGui.PushID(iconText); + ImGui.PushFont(UiBuilder.IconFont); - - var button = ImGui.Button(iconText); - + var iconSize = ImGui.CalcTextSize(icon); ImGui.PopFont(); + + var dl = ImGui.GetWindowDrawList(); + var cursor = ImGui.GetCursorScreenPos(); + + // Draw an ImGui button with the icon and text + var buttonWidth = iconSize.X + (ImGui.GetStyle().FramePadding.X * 2); + var buttonHeight = ImGui.GetFrameHeight(); + var button = ImGui.Button(string.Empty, new Vector2(buttonWidth, buttonHeight)); + + // Draw the icon on the window drawlist + var iconPos = new Vector2(cursor.X + ImGui.GetStyle().FramePadding.X, cursor.Y + ImGui.GetStyle().FramePadding.Y); + + ImGui.PushFont(UiBuilder.IconFont); + dl.AddText(iconPos, ImGui.GetColorU32(ImGuiCol.Text), icon); + ImGui.PopFont(); + + ImGui.PopID(); if (numColors > 0) ImGui.PopStyleColor(numColors); @@ -167,7 +188,7 @@ public static partial class ImGuiComponents // Draw an ImGui button with the icon and text var buttonWidth = iconSize.X + textSize.X + (ImGui.GetStyle().FramePadding.X * 2) + iconPadding; - var buttonHeight = Math.Max(iconSize.Y, textSize.Y) + (ImGui.GetStyle().FramePadding.Y * 2); + var buttonHeight = ImGui.GetFrameHeight(); var button = ImGui.Button(string.Empty, new Vector2(buttonWidth, buttonHeight)); // Draw the icon on the window drawlist From a1f1c169dce5ebe244826bb5df6e35f4fc5cdf17 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sun, 1 Oct 2023 12:01:58 -0700 Subject: [PATCH 117/120] Allow icon 180000 --- .../Internal/Windows/Data/Widgets/IconBrowserWidget.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs index b37878045..dcae6e689 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/IconBrowserWidget.cs @@ -16,7 +16,7 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets; public class IconBrowserWidget : IDataWindowWidget { // Remove range 170,000 -> 180,000 by default, this specific range causes exceptions. - private readonly HashSet nullValues = Enumerable.Range(170000, 10000).ToHashSet(); + private readonly HashSet nullValues = Enumerable.Range(170000, 9999).ToHashSet(); private Vector2 iconSize = new(64.0f, 64.0f); private Vector2 editIconSize = new(64.0f, 64.0f); From 2bdb83757700d6ad138ed0509ad125e0a8a9b7a2 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 1 Oct 2023 21:12:27 +0200 Subject: [PATCH 118/120] feat: enable early loaded services to wait for provided services, some rewrites to make service kind declaration more explicit --- Dalamud/Dalamud.cs | 19 +++++----- .../Interface/Internal/InterfaceManager.cs | 1 + Dalamud/ServiceManager.cs | 36 +++++++++---------- Dalamud/Service{T}.cs | 7 ++++ 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 8a75049ad..f50a39aa3 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -74,14 +74,17 @@ internal sealed class Dalamud : IServiceType if (!configuration.IsResumeGameAfterPluginLoad) { NativeFunctions.SetEvent(mainThreadContinueEvent); - try - { - _ = ServiceManager.InitializeEarlyLoadableServices(); - } - catch (Exception e) - { - Log.Error(e, "Service initialization failure"); - } + ServiceManager.InitializeEarlyLoadableServices() + .ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + return; + + Log.Error(t.Exception!, "Service initialization failure"); + Util.Fatal( + "Dalamud failed to load all necessary services.\n\nThe game will continue, but you may not be able to use plugins.", + "Dalamud", false); + }); } else { diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index dd85f1db4..93d9bb1dd 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -1276,6 +1276,7 @@ internal class InterfaceManager : IDisposable, IServiceType /// /// Represents an instance of InstanceManager with scene ready for use. /// + [ServiceManager.Service] public class InterfaceManagerWithScene : IServiceType { /// diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index e8512e854..553e0a4af 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -47,9 +47,9 @@ internal static class ServiceManager None = 0, /// - /// Regular service. + /// Service that is loaded manually. /// - ManualService = 1 << 0, + ProvidedService = 1 << 0, /// /// Service that is loaded asynchronously while the game starts. @@ -90,7 +90,7 @@ internal static class ServiceManager { void ProvideService(T service) where T : IServiceType { - Debug.Assert(typeof(T).GetServiceKind().HasFlag(ServiceKind.ManualService), "Provided service must have Service attribute"); + Debug.Assert(typeof(T).GetServiceKind().HasFlag(ServiceKind.ProvidedService), "Provided service must have Service attribute"); Service.Provide(service); LoadedServices.Add(typeof(T)); } @@ -119,23 +119,18 @@ internal static class ServiceManager var serviceContainer = Service.Get(); - foreach (var serviceType in Assembly.GetExecutingAssembly().GetTypes()) + foreach (var serviceType in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsAssignableTo(typeof(IServiceType)) && !x.IsInterface && !x.IsAbstract)) { var serviceKind = serviceType.GetServiceKind(); if (serviceKind is ServiceKind.None) - continue; + throw new Exception($"Service<{serviceType.FullName}> did not specify a kind"); // Let IoC know about the interfaces this service implements serviceContainer.RegisterInterfaces(serviceType); // Scoped service do not go through Service and are never early loaded - // Manual services are provided - if (serviceKind.HasFlag(ServiceKind.ScopedService) || serviceKind.HasFlag(ServiceKind.ManualService)) + if (serviceKind.HasFlag(ServiceKind.ScopedService)) continue; - - Debug.Assert( - !serviceKind.HasFlag(ServiceKind.ManualService) && !serviceKind.HasFlag(ServiceKind.ScopedService), - "Regular and scoped services should never be loaded early"); var genericWrappedServiceType = typeof(Service<>).MakeGenericType(serviceType); @@ -147,9 +142,14 @@ internal static class ServiceManager null, null); + getAsyncTaskMap[serviceType] = getTask; + + // We don't actually need to load provided services, something else does + if (serviceKind.HasFlag(ServiceKind.ProvidedService)) + continue; + if (serviceKind.HasFlag(ServiceKind.BlockingEarlyLoadedService)) { - getAsyncTaskMap[serviceType] = getTask; blockingEarlyLoadingServices.Add(serviceType); } else @@ -191,13 +191,13 @@ internal static class ServiceManager var hasDeps = true; foreach (var dependency in dependencyServicesMap[serviceType]) { - var depServiceKind = dependency.GetServiceKind(); - var depResolveTask = getAsyncTaskMap.GetValueOrDefault(dependency); + var depUnderlyingServiceType = dependency.GetGenericArguments().First(); + var depResolveTask = getAsyncTaskMap.GetValueOrDefault(depUnderlyingServiceType); - if (depResolveTask == null && (depServiceKind.HasFlag(ServiceKind.EarlyLoadedService) || depServiceKind.HasFlag(ServiceKind.BlockingEarlyLoadedService))) + if (depResolveTask == null) { - Log.Error("{Type}: {Dependency} has no resolver task, is it early loaded or blocking early loaded?", serviceType.FullName!, dependency.FullName!); - Debug.Assert(false, $"No resolver for dependent service {dependency.FullName}"); + Log.Error("{Type}: {Dependency} has no resolver task", serviceType.FullName!, dependency.FullName!); + Debug.Assert(false, $"No resolver for dependent service {depUnderlyingServiceType.FullName}"); } else if (depResolveTask is { IsCompleted: false }) { @@ -386,7 +386,7 @@ internal static class ServiceManager if (attr.IsAssignableTo(typeof(ScopedService))) return ServiceKind.ScopedService; - return ServiceKind.ManualService; + return ServiceKind.ProvidedService; } /// diff --git a/Dalamud/Service{T}.cs b/Dalamud/Service{T}.cs index 539941c27..b609c9082 100644 --- a/Dalamud/Service{T}.cs +++ b/Dalamud/Service{T}.cs @@ -123,6 +123,8 @@ internal static class Service where T : IServiceType public static List GetDependencyServices() { var res = new List(); + + ServiceManager.Log.Verbose("Service<{0}>: Getting dependencies", typeof(T).Name); var ctor = GetServiceConstructor(); if (ctor != null) @@ -181,6 +183,11 @@ internal static class Service where T : IServiceType res.Add(serviceType); } } + + foreach (var type in res) + { + ServiceManager.Log.Verbose("Service<{0}>: => Dependency: {1}", typeof(T).Name, type.Name); + } return res .Distinct() From 263771c0824c78ab1f1959fee3a402c3770842d4 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 1 Oct 2023 21:35:21 +0200 Subject: [PATCH 119/120] chore: move all dalamud logo textures into special service --- Dalamud/Interface/Internal/Branding.cs | 58 +++++++++++++++++++ .../Interface/Internal/DalamudInterface.cs | 28 ++------- .../Internal/Windows/ChangelogWindow.cs | 6 +- .../Internal/Windows/PluginImageCache.cs | 5 +- .../Windows/Settings/Tabs/SettingsTabAbout.cs | 5 +- Dalamud/ServiceManager.cs | 10 +++- 6 files changed, 77 insertions(+), 35 deletions(-) create mode 100644 Dalamud/Interface/Internal/Branding.cs diff --git a/Dalamud/Interface/Internal/Branding.cs b/Dalamud/Interface/Internal/Branding.cs new file mode 100644 index 000000000..4162cabeb --- /dev/null +++ b/Dalamud/Interface/Internal/Branding.cs @@ -0,0 +1,58 @@ +using System.IO; + +using Dalamud.IoC.Internal; + +namespace Dalamud.Interface.Internal; + +/// +/// Class containing various textures used by Dalamud windows for branding purposes. +/// +[ServiceManager.EarlyLoadedService] +#pragma warning disable SA1015 +[InherentDependency] // Can't load textures before this +#pragma warning restore SA1015 +internal class Branding : IServiceType, IDisposable +{ + private readonly Dalamud dalamud; + private readonly TextureManager tm; + + /// + /// Initializes a new instance of the class. + /// + /// Dalamud instance. + /// TextureManager instance. + [ServiceManager.ServiceConstructor] + public Branding(Dalamud dalamud, TextureManager tm) + { + this.dalamud = dalamud; + this.tm = tm; + + this.LoadTextures(); + } + + /// + /// Gets a full-size Dalamud logo texture. + /// + public IDalamudTextureWrap Logo { get; private set; } = null!; + + /// + /// Gets a small Dalamud logo texture. + /// + public IDalamudTextureWrap LogoSmall { get; private set; } = null!; + + /// + public void Dispose() + { + this.Logo.Dispose(); + this.LogoSmall.Dispose(); + } + + private void LoadTextures() + { + this.Logo = this.tm.GetTextureFromFile(new FileInfo(Path.Combine(this.dalamud.AssetDirectory.FullName, "UIRes", "logo.png"))) + ?? throw new Exception("Could not load logo."); + + this.LogoSmall = this.tm.GetTextureFromFile(new FileInfo(Path.Combine(this.dalamud.AssetDirectory.FullName, "UIRes", "tsmLogo.png"))) + ?? throw new Exception("Could not load TSM logo."); + } +} diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index 9e4c215b3..a7b1e80b5 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -66,9 +66,6 @@ internal class DalamudInterface : IDisposable, IServiceType private readonly BranchSwitcherWindow branchSwitcherWindow; private readonly HitchSettingsWindow hitchSettingsWindow; - private readonly IDalamudTextureWrap logoTexture; - private readonly IDalamudTextureWrap tsmLogoTexture; - private bool isCreditsDarkening = false; private OutCubic creditsDarkeningAnimation = new(TimeSpan.FromSeconds(10)); @@ -92,7 +89,8 @@ internal class DalamudInterface : IDisposable, IServiceType Dalamud dalamud, DalamudConfiguration configuration, InterfaceManager.InterfaceManagerWithScene interfaceManagerWithScene, - PluginImageCache pluginImageCache) + PluginImageCache pluginImageCache, + Branding branding) { var interfaceManager = interfaceManagerWithScene.Manager; this.WindowSystem = new WindowSystem("DalamudCore"); @@ -136,26 +134,13 @@ internal class DalamudInterface : IDisposable, IServiceType interfaceManager.Draw += this.OnDraw; - var logoTex = - interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png")); - var tsmLogoTex = - interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "tsmLogo.png")); - - if (logoTex == null || tsmLogoTex == null) - { - throw new Exception("Failed to load logo textures"); - } - - this.logoTexture = logoTex; - this.tsmLogoTexture = tsmLogoTex; - var tsm = Service.Get(); - tsm.AddEntryCore(Loc.Localize("TSMDalamudPlugins", "Plugin Installer"), this.tsmLogoTexture, this.OpenPluginInstaller); - tsm.AddEntryCore(Loc.Localize("TSMDalamudSettings", "Dalamud Settings"), this.tsmLogoTexture, this.OpenSettings); + tsm.AddEntryCore(Loc.Localize("TSMDalamudPlugins", "Plugin Installer"), branding.LogoSmall, this.OpenPluginInstaller); + tsm.AddEntryCore(Loc.Localize("TSMDalamudSettings", "Dalamud Settings"), branding.LogoSmall, this.OpenSettings); if (!configuration.DalamudBetaKind.IsNullOrEmpty()) { - tsm.AddEntryCore(Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), this.tsmLogoTexture, () => this.isImGuiDrawDevMenu = true); + tsm.AddEntryCore(Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), branding.LogoSmall, () => this.isImGuiDrawDevMenu = true); } this.creditsDarkeningAnimation.Point1 = Vector2.Zero; @@ -192,9 +177,6 @@ internal class DalamudInterface : IDisposable, IServiceType this.consoleWindow.Dispose(); this.pluginWindow.Dispose(); this.titleScreenMenuWindow.Dispose(); - - this.logoTexture.Dispose(); - this.tsmLogoTexture.Dispose(); } #region Open diff --git a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs index 61010ce0c..cd4618f24 100644 --- a/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ChangelogWindow.cs @@ -49,11 +49,7 @@ Thanks and have fun!"; this.Size = new Vector2(885, 463); this.SizeCondition = ImGuiCond.Appearing; - var interfaceManager = Service.Get(); - var dalamud = Service.Get(); - - this.logoTexture = - interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png"))!; + this.logoTexture = Service.Get().Logo; } /// diff --git a/Dalamud/Interface/Internal/Windows/PluginImageCache.cs b/Dalamud/Interface/Internal/Windows/PluginImageCache.cs index c334cd4bd..b721b08c3 100644 --- a/Dalamud/Interface/Internal/Windows/PluginImageCache.cs +++ b/Dalamud/Interface/Internal/Windows/PluginImageCache.cs @@ -50,6 +50,9 @@ internal class PluginImageCache : IDisposable, IServiceType [ServiceManager.ServiceDependency] private readonly InterfaceManager.InterfaceManagerWithScene imWithScene = Service.Get(); + [ServiceManager.ServiceDependency] + private readonly Branding branding = Service.Get(); + [ServiceManager.ServiceDependency] private readonly HappyHttpClient happyHttpClient = Service.Get(); @@ -88,7 +91,7 @@ internal class PluginImageCache : IDisposable, IServiceType this.installedIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "installedIcon.png"))) ?? this.emptyTextureTask).Unwrap(); this.thirdIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "thirdIcon.png"))) ?? this.emptyTextureTask).Unwrap(); this.thirdInstalledIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "thirdInstalledIcon.png"))) ?? this.emptyTextureTask).Unwrap(); - this.corePluginIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "tsmLogo.png"))) ?? this.emptyTextureTask).Unwrap(); + this.corePluginIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(this.branding.LogoSmall)).Unwrap(); this.downloadTask = Task.Factory.StartNew( () => this.DownloadTask(8), TaskCreationOptions.LongRunning); diff --git a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs index ec9833b78..9b6a32617 100644 --- a/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs +++ b/Dalamud/Interface/Internal/Windows/Settings/Tabs/SettingsTabAbout.cs @@ -181,10 +181,9 @@ Contribute at: https://github.com/goatcorp/Dalamud public SettingsTabAbout() { - var dalamud = Service.Get(); - var interfaceManager = Service.Get(); + var branding = Service.Get(); - this.logoTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png"))!; + this.logoTexture = branding.Logo; this.creditsThrottler = new(); } diff --git a/Dalamud/ServiceManager.cs b/Dalamud/ServiceManager.cs index 553e0a4af..453fa3530 100644 --- a/Dalamud/ServiceManager.cs +++ b/Dalamud/ServiceManager.cs @@ -16,7 +16,7 @@ using JetBrains.Annotations; namespace Dalamud; // TODO: -// - Unify dependency walking code(load/unload +// - Unify dependency walking code(load/unload) // - Visualize/output .dot or imgui thing /// @@ -122,8 +122,7 @@ internal static class ServiceManager foreach (var serviceType in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsAssignableTo(typeof(IServiceType)) && !x.IsInterface && !x.IsAbstract)) { var serviceKind = serviceType.GetServiceKind(); - if (serviceKind is ServiceKind.None) - throw new Exception($"Service<{serviceType.FullName}> did not specify a kind"); + Debug.Assert(serviceKind != ServiceKind.None, $"Service<{serviceType.FullName}> did not specify a kind"); // Let IoC know about the interfaces this service implements serviceContainer.RegisterInterfaces(serviceType); @@ -148,6 +147,11 @@ internal static class ServiceManager if (serviceKind.HasFlag(ServiceKind.ProvidedService)) continue; + Debug.Assert( + serviceKind.HasFlag(ServiceKind.EarlyLoadedService) || + serviceKind.HasFlag(ServiceKind.BlockingEarlyLoadedService), + "At this point, service must be either early loaded or blocking early loaded"); + if (serviceKind.HasFlag(ServiceKind.BlockingEarlyLoadedService)) { blockingEarlyLoadingServices.Add(serviceType); From bef5e7c3f520e6c484babf8e06716de9934cf63d Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 1 Oct 2023 22:13:29 +0200 Subject: [PATCH 120/120] fix: we need ReliableFileStorage still when disposing config --- Dalamud/Configuration/Internal/DalamudConfiguration.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 1e9bc1523..65f10c4ba 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -6,6 +5,7 @@ using System.Linq; using Dalamud.Game.Text; using Dalamud.Interface.Style; +using Dalamud.IoC.Internal; using Dalamud.Plugin.Internal.Profiles; using Dalamud.Storage; using Dalamud.Utility; @@ -20,6 +20,9 @@ namespace Dalamud.Configuration.Internal; /// [Serializable] [ServiceManager.Service] +#pragma warning disable SA1015 +[InherentDependency] // We must still have this when unloading +#pragma warning restore SA1015 internal sealed class DalamudConfiguration : IServiceType, IDisposable { private static readonly JsonSerializerSettings SerializerSettings = new()