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(); +}