diff --git a/PlayerTags/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index 79f1037..262953d 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -9,6 +9,9 @@ using System.Linq; namespace PlayerTags.Features { + /// + /// A feature that adds options for the management of custom tags to context menus. + /// public class CustomTagsContextMenuFeature : IDisposable { private string?[] SupportedAddonNames = new string?[] @@ -62,47 +65,6 @@ namespace PlayerTags.Features private void ContextMenuHooks_ContextMenuOpened(ContextMenuOpenedArgs contextMenuOpenedArgs) { - if (contextMenuOpenedArgs.GameObjectContext != null) - { - PluginLog.Debug($"ContextMenuHooks_ContextMenuOpened {contextMenuOpenedArgs.GameObjectContext?.Id} {contextMenuOpenedArgs.GameObjectContext?.ContentIdLower} '{contextMenuOpenedArgs.GameObjectContext?.Name}' {contextMenuOpenedArgs.GameObjectContext?.WorldId}"); - } - - if (contextMenuOpenedArgs.ItemContext != null) - { - PluginLog.Debug($"ContextMenuHooks_ContextMenuOpened {contextMenuOpenedArgs.ItemContext?.Id} {contextMenuOpenedArgs.ItemContext?.Count} {contextMenuOpenedArgs.ItemContext?.IsHighQuality}"); - } - - contextMenuOpenedArgs.ContextMenuItems.Add(new CustomContextMenuItem("Root1", (itemSelectedArgs => - { - PluginLog.Debug("Executed Root1"); - }))); - - contextMenuOpenedArgs.ContextMenuItems.Add(new OpenSubContextMenuItem("Root2", (subContextMenuOpenedArgs => - { - PluginLog.Debug("Executed Root2"); - - List newContextMenuItems = new List(); - newContextMenuItems.Add(new OpenSubContextMenuItem("Inner1", (subContextMenuOpenedArgs2 => - { - PluginLog.Debug("Executed Inner1"); - - List newContextMenuItems = new List(); - newContextMenuItems.Add(new CustomContextMenuItem("Inner3", (itemSelectedArgs => - { - PluginLog.Debug("Executed Inner3"); - }))); - - subContextMenuOpenedArgs2.ContextMenuItems.InsertRange(0, newContextMenuItems); - }))); - - newContextMenuItems.Add(new CustomContextMenuItem("Inner2", (itemSelectedArgs => - { - PluginLog.Debug("Executed Inner2"); - }))); - - subContextMenuOpenedArgs.ContextMenuItems.InsertRange(0, newContextMenuItems); - }))); - if (!m_PluginConfiguration.IsCustomTagsContextMenuEnabled || !SupportedAddonNames.Contains(contextMenuOpenedArgs.ParentAddonName)) { return; diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index c3eb394..cbb0705 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -97,7 +97,7 @@ namespace PlayerTags.Features private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) { - var beforeTitleHashCode = args.Title.GetHashCode(); + var beforeTitleBytes = args.Title.Encode(); AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany/*, out isNameChanged, out isTitleChanged, out isFreeCompanyChanged*/); if (m_PluginConfiguration.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) @@ -122,7 +122,7 @@ namespace PlayerTags.Features } else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags) { - bool hasTitleChanged = beforeTitleHashCode != args.Title.GetHashCode(); + bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(args.Title.Encode()); args.IsTitleVisible = hasTitleChanged; } @@ -132,7 +132,6 @@ namespace PlayerTags.Features else if (m_PluginConfiguration.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never) { args.FreeCompany.Payloads.Clear(); - //isFreeCompanyChanged = true; } } diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs index c76218e..e182f3c 100644 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs +++ b/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs @@ -121,20 +121,20 @@ namespace PlayerTags.GameInterface.ContextMenus private delegate IntPtr GetAddonByIdDelegate_Unmanaged(IntPtr raptureAtkUnitManager, ushort id); private readonly GetAddonByIdDelegate_Unmanaged? m_GetAddonById; - private delegate byte OpenSubContextMenuDelegate_Unmanaged(IntPtr agent); + private delegate bool OpenSubContextMenuDelegate_Unmanaged(IntPtr agent); private readonly OpenSubContextMenuDelegate_Unmanaged? m_OpenSubContextMenu; private delegate IntPtr ContextMenuOpeningDelegate_Unmanaged(IntPtr a1, IntPtr a2, IntPtr a3, uint a4, IntPtr a5, IntPtr agent, IntPtr a7, ushort a8); private Hook? m_ContextMenuOpeningHook; - private unsafe delegate byte ContextMenuOpenedDelegate_Unmanaged(IntPtr addon, int menuSize, AtkValue* atkValueArgs); + private unsafe delegate bool ContextMenuOpenedDelegate_Unmanaged(IntPtr addon, int menuSize, AtkValue* atkValueArgs); private Hook? m_ContextMenuOpenedHook; private Hook? m_SubContextMenuOpenedHook; - private delegate byte ContextMenuItemSelectedDelegate_Unmanaged(IntPtr addon, int index, byte a3); + private delegate bool ContextMenuItemSelectedDelegate_Unmanaged(IntPtr addon, int index, byte a3); private Hook? m_ContextMenuItemSelectedHook; - private delegate byte SubContextMenuOpeningDelegate_Unmanaged(IntPtr agent); + private delegate bool SubContextMenuOpeningDelegate_Unmanaged(IntPtr agent); private Hook? m_SubContextMenuOpeningHook; private delegate IntPtr OpenInventoryContextMenuDelegate_Unmanaged(IntPtr agent, byte hasTitle, byte zero); @@ -150,8 +150,8 @@ namespace PlayerTags.GameInterface.ContextMenus private IntPtr m_CurrentContextMenuAgent; private IntPtr m_CurrentSubContextMenuTitle; - private ContextMenuOpenedArgs? m_ContextMenuOpenedArgs; - private OpenSubContextMenuItem? m_OpenSubContextMenuItem; + private ContextMenuItem? m_CurrentSelectedItem; + private ContextMenuOpenedArgs? m_CurrentContextMenuOpenedArgs; /// /// Occurs when a context menu is opened by the game. @@ -279,12 +279,12 @@ namespace PlayerTags.GameInterface.ContextMenus return m_ContextMenuOpeningHook!.Original(a1, a2, a3, a4, a5, agent, a7, a8); } - private unsafe byte ContextMenuOpenedDetour(IntPtr addon, int atkValueCount, AtkValue* atkValues) + private unsafe bool ContextMenuOpenedDetour(IntPtr addon, int atkValueCount, AtkValue* atkValues) { PluginLog.Debug($"ContextMenuOpenedDetour"); if (m_ContextMenuOpenedHook == null) { - return 0; + return false; } var addonContext = (AddonContext*)addon; @@ -306,7 +306,7 @@ namespace PlayerTags.GameInterface.ContextMenus private unsafe void ContextMenuOpenedImplementation(IntPtr addon, ref int atkValueCount, ref AtkValue* atkValues) { - PluginLog.Debug($"ContextMenuOpenedImplementation"); + PluginLog.Debug($"ContextMenuOpenedImplementation {m_CurrentSelectedItem}"); if (m_AtkValueChangeType == null || m_AtkValueSetString == null @@ -316,19 +316,21 @@ namespace PlayerTags.GameInterface.ContextMenus return; } - ContextMenuReaderWriter contextMenuReaderWriter = new ContextMenuReaderWriter(m_CurrentContextMenuAgent, atkValueCount, atkValues); - - // Read the context menu items from the game, then allow subscribers to modify them - if (m_ContextMenuOpenedArgs == null) + ContextMenuOpenedDelegate contextMenuOpenedDelegate = ContextMenuOpened; + if (m_CurrentSelectedItem is OpenSubContextMenuItem openSubContextMenuItem) { - m_ContextMenuOpenedArgs = NotifyContextMenuOpened(addon, m_CurrentContextMenuAgent, ContextMenuOpened, contextMenuReaderWriter.Read()); - if (m_ContextMenuOpenedArgs == null) - { - return; - } + contextMenuOpenedDelegate = openSubContextMenuItem.OpenedAction; } - contextMenuReaderWriter.Write(null, m_ContextMenuOpenedArgs.ContextMenuItems, m_AtkValueChangeType, m_AtkValueSetString); + // Read the context menu items from the game, then allow subscribers to modify them + ContextMenuReaderWriter contextMenuReaderWriter = new ContextMenuReaderWriter(m_CurrentContextMenuAgent, atkValueCount, atkValues); + m_CurrentContextMenuOpenedArgs = NotifyContextMenuOpened(addon, m_CurrentContextMenuAgent, m_CurrentSelectedItem, contextMenuOpenedDelegate, contextMenuReaderWriter.Read()); + if (m_CurrentContextMenuOpenedArgs == null) + { + return; + } + + contextMenuReaderWriter.Write(m_CurrentContextMenuOpenedArgs, m_AtkValueChangeType, m_AtkValueSetString); // Update the addon var addonContext = (AddonContext*)addon; @@ -336,17 +338,17 @@ namespace PlayerTags.GameInterface.ContextMenus atkValues = *(&addonContext->AtkValues) = contextMenuReaderWriter.AtkValues; } - private byte SubContextMenuOpeningDetour(IntPtr agent) + private bool SubContextMenuOpeningDetour(IntPtr agent) { PluginLog.Debug($"SubContextMenuOpeningDetour"); if (m_SubContextMenuOpeningHook == null) { - return 0; + return false; } if (SubContextMenuOpeningImplementation(agent)) { - return 0x0; + return true; } return m_SubContextMenuOpeningHook.Original(agent); @@ -354,27 +356,16 @@ namespace PlayerTags.GameInterface.ContextMenus private unsafe bool SubContextMenuOpeningImplementation(IntPtr agent) { - PluginLog.Debug($"SubContextMenuOpeningImplementation {m_OpenSubContextMenuItem}"); + PluginLog.Debug($"SubContextMenuOpeningImplementation {m_CurrentSelectedItem}"); if (m_OpenSubContextMenu == null || m_OpenInventoryContextMenu == null || m_AtkValueChangeType == null - || m_OpenSubContextMenuItem == null) + || !(m_CurrentSelectedItem is OpenSubContextMenuItem)) { return false; } - // This isn't our own sub context menu -- don't go any further - //if (m_OpenSubContextMenuItem == null) - //{ - // return false; - //} - - //var a = (AgentContext*)agent; - //var s = a->SelectedIndex; - - //*(&a->SelectedIndex) = 0xff; - // The important things to make this work are: // 1. Temporary allocate a sub context menu title // 1. Temporarily increase the atk value count by 1 so the game knows to expect at least 1 context menu item @@ -398,8 +389,6 @@ namespace PlayerTags.GameInterface.ContextMenus *(&agentContext->SubContextMenuTitle) = (byte*)m_CurrentSubContextMenuTitle; } - //*(&a->SelectedIndex) = s; - var atkValues = &agentContext->ItemData->AtkValues; // Let the game know the context menu will have at least 1 item in it @@ -412,22 +401,17 @@ namespace PlayerTags.GameInterface.ContextMenus return true; } - private unsafe byte SubContextMenuOpenedDetour(IntPtr addon, int atkValueCount, AtkValue* atkValues) + private unsafe bool SubContextMenuOpenedDetour(IntPtr addon, int atkValueCount, AtkValue* atkValues) { PluginLog.Debug($"SubContextMenuOpenedDetour"); if (m_SubContextMenuOpenedHook == null) { - return 0; + return false; } - var addonContext = (AddonContext*)addon; - PluginLog.Debug($"SubContextMenuOpenedDetour addonContext->IsInitialMenu={addonContext->IsInitialMenu}"); - - ContextMenuReaderWriter.Print(atkValueCount, atkValues); - try { - SubContextMenuOpenedImplementation(addon, ref atkValueCount, ref atkValues); + ContextMenuOpenedImplementation(addon, ref atkValueCount, ref atkValues); } catch (Exception ex) { @@ -437,57 +421,16 @@ namespace PlayerTags.GameInterface.ContextMenus return m_SubContextMenuOpenedHook.Original(addon, atkValueCount, atkValues); } - private unsafe void SubContextMenuOpenedImplementation(IntPtr addon, ref int atkValueCount, ref AtkValue* atkValues) - { - PluginLog.Debug($"SubContextMenuOpenedImplementation"); - - if (m_AtkValueSetString == null - || m_AtkValueChangeType == null - || ContextMenuOpened == null) - { - return; - } - - ContextMenuReaderWriter contextMenuReader = new ContextMenuReaderWriter(m_CurrentContextMenuAgent, atkValueCount, atkValues); - - if (m_OpenSubContextMenuItem != null) - { - m_ContextMenuOpenedArgs = NotifyContextMenuOpened(addon, m_CurrentContextMenuAgent, m_OpenSubContextMenuItem.OpenedAction, contextMenuReader.Read()); - if (m_ContextMenuOpenedArgs == null) - { - return; - } - } - else - { - m_ContextMenuOpenedArgs = NotifyContextMenuOpened(addon, m_CurrentContextMenuAgent, ContextMenuOpened, contextMenuReader.Read()); - if (m_ContextMenuOpenedArgs == null) - { - return; - } - } - - contextMenuReader.Write(m_OpenSubContextMenuItem, m_ContextMenuOpenedArgs.ContextMenuItems, m_AtkValueChangeType, m_AtkValueSetString); - - // Update the addon - var addonContext = (AddonContext*)addon; - atkValueCount = *(&addonContext->AtkValuesCount) = (ushort)contextMenuReader.AtkValueCount; - atkValues = *(&addonContext->AtkValues) = contextMenuReader.AtkValues; - } - - private unsafe ContextMenuOpenedArgs? NotifyContextMenuOpened(IntPtr addon, IntPtr agent, ContextMenuOpenedDelegate contextMenuOpenedDelegate, IEnumerable initialContextMenuItems) + private unsafe ContextMenuOpenedArgs? NotifyContextMenuOpened(IntPtr addon, IntPtr agent, ContextMenuItem? selectedContextMenuItem, ContextMenuOpenedDelegate contextMenuOpenedDelegate, IEnumerable initialContextMenuItems) { var parentAddonName = GetParentAddonName(addon); - ContextMenuOpenedArgs contextMenuOpenedArgs; + ItemContext? itemContext = null; + GameObjectContext? gameObjectContext = null; if (IsInventoryContext(agent)) { var agentInventoryContext = (AgentInventoryContext*)agent; - - contextMenuOpenedArgs = new ContextMenuOpenedArgs(addon, agent, parentAddonName, initialContextMenuItems) - { - ItemContext = new ItemContext(agentInventoryContext->ItemId, agentInventoryContext->ItemCount, agentInventoryContext->IsHighQuality) - }; + itemContext = new ItemContext(agentInventoryContext->ItemId, agentInventoryContext->ItemCount, agentInventoryContext->IsHighQuality); } else { @@ -499,12 +442,16 @@ namespace PlayerTags.GameInterface.ContextMenus objectName = GameInterfaceHelper.ReadSeString((IntPtr)agentContext->ObjectName.StringPtr); } - contextMenuOpenedArgs = new ContextMenuOpenedArgs(addon, agent, parentAddonName, initialContextMenuItems) - { - GameObjectContext = new GameObjectContext(agentContext->ObjectId, agentContext->ObjectContentIdLower, objectName, agentContext->ObjectWorldId) - }; + gameObjectContext = new GameObjectContext(agentContext->ObjectId, agentContext->ObjectContentIdLower, objectName, agentContext->ObjectWorldId); } + var contextMenuOpenedArgs = new ContextMenuOpenedArgs(addon, agent, parentAddonName, initialContextMenuItems) + { + SelectedItem = selectedContextMenuItem, + ItemContext = itemContext, + GameObjectContext = gameObjectContext + }; + try { contextMenuOpenedDelegate.Invoke(contextMenuOpenedArgs); @@ -529,12 +476,12 @@ namespace PlayerTags.GameInterface.ContextMenus return contextMenuOpenedArgs; } - private unsafe byte ContextMenuItemSelectedDetour(IntPtr addon, int index, byte a3) + private unsafe bool ContextMenuItemSelectedDetour(IntPtr addon, int index, byte a3) { - PluginLog.Debug($"ContextMenuItemSelectedDetour"); + PluginLog.Debug($"ContextMenuItemSelectedDetour index={index}"); if (m_ContextMenuItemSelectedHook == null) { - return 0; + return false; } try @@ -553,10 +500,10 @@ namespace PlayerTags.GameInterface.ContextMenus { PluginLog.Debug($"ContextMenuItemSelectedImplementation index={index}"); - if (m_ContextMenuOpenedArgs == null) + if (m_CurrentContextMenuOpenedArgs == null) { - m_ContextMenuOpenedArgs = null; - m_OpenSubContextMenuItem = null; + m_CurrentContextMenuOpenedArgs = null; + m_CurrentSelectedItem = null; return; } @@ -564,39 +511,31 @@ namespace PlayerTags.GameInterface.ContextMenus var addonContext = (AddonContext*)addon; ContextMenuReaderWriter.Print(addonContext->AtkValuesCount, addonContext->AtkValues); - var contextMenuItem = m_ContextMenuOpenedArgs.ContextMenuItems.ElementAtOrDefault(index); + var contextMenuItem = m_CurrentContextMenuOpenedArgs.ContextMenuItems.ElementAtOrDefault(index); if (contextMenuItem == null) { - m_ContextMenuOpenedArgs = null; - m_OpenSubContextMenuItem = null; + m_CurrentContextMenuOpenedArgs = null; + m_CurrentSelectedItem = null; return; } - if (contextMenuItem is OpenSubContextMenuItem openSubContextMenuItem) + if (contextMenuItem is CustomContextMenuItem customContextMenuItem) { - m_OpenSubContextMenuItem = openSubContextMenuItem; - } - else if (contextMenuItem is CustomContextMenuItem customContextMenuItem) - { - var args = new CustomContextMenuItemSelectedArgs(m_ContextMenuOpenedArgs, customContextMenuItem); - try { - customContextMenuItem.CustomAction(args); + var customContextMenuItemSelectedArgs = new CustomContextMenuItemSelectedArgs(m_CurrentContextMenuOpenedArgs, customContextMenuItem); + customContextMenuItem.ItemSelected(customContextMenuItemSelectedArgs); } catch (Exception ex) { PluginLog.LogError(ex, "ContextMenuItemSelectedImplementation"); } + } - m_ContextMenuOpenedArgs = null; - m_OpenSubContextMenuItem = null; - } - else - { - m_ContextMenuOpenedArgs = null; - m_OpenSubContextMenuItem = null; - } + m_CurrentSelectedItem = contextMenuItem;// is OpenSubContextMenuItem ? contextMenuItem : null; + m_CurrentContextMenuOpenedArgs = null; + + PluginLog.Debug($"ContextMenuItemSelectedImplementation index={index} dddddddddddddd"); } private void InventoryContextMenuEvent30Detour(IntPtr agent, IntPtr a2, int a3, int a4, short a5) diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs index f4e30ae..d45c9f0 100644 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs +++ b/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs @@ -14,6 +14,8 @@ namespace PlayerTags.GameInterface.ContextMenus public List ContextMenuItems { get; } + public ContextMenuItem? SelectedItem { get; init; } + public GameObjectContext? GameObjectContext { get; init; } public ItemContext? ItemContext { get; init; } diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs index d688745..eae16bc 100644 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs +++ b/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs @@ -278,11 +278,11 @@ namespace PlayerTags.GameInterface.ContextMenus return gameContextMenuItems.ToArray(); } - public unsafe void Write(OpenSubContextMenuItem? selectedOpenSubContextMenuItem, IEnumerable contextMenuItems, AtkValueChangeTypeDelegate_Unmanaged atkValueChangeType, AtkValueSetStringDelegate_Unmanaged atkValueSetString) + public unsafe void Write(ContextMenuOpenedArgs contextMenuOpenedArgs, AtkValueChangeTypeDelegate_Unmanaged atkValueChangeType, AtkValueSetStringDelegate_Unmanaged atkValueSetString) { Print(); - var newAtkValuesCount = FirstContextMenuItemIndex + (contextMenuItems.Count() * TotalDesiredAtkValuesPerContextMenuItem); + var newAtkValuesCount = FirstContextMenuItemIndex + (contextMenuOpenedArgs.ContextMenuItems.Count() * TotalDesiredAtkValuesPerContextMenuItem); // Allocate the new array. We have to do a little dance with the first 8 bytes which represents the array count const int arrayCountSize = 8; @@ -311,11 +311,11 @@ namespace PlayerTags.GameInterface.ContextMenus m_AtkValueCount = newAtkValuesCount; m_AtkValues = newAtkValues; - // Set the title - if (selectedOpenSubContextMenuItem != null) + // Set the custom title if appropriate + if (contextMenuOpenedArgs.SelectedItem is OpenSubContextMenuItem) { var titleAtkValue = &m_AtkValues[1]; - fixed (byte* TtlePtr = selectedOpenSubContextMenuItem.Name.Encode().NullTerminate()) + fixed (byte* TtlePtr = contextMenuOpenedArgs.SelectedItem.Name.Encode().NullTerminate()) { atkValueSetString(titleAtkValue, TtlePtr); } @@ -324,7 +324,7 @@ namespace PlayerTags.GameInterface.ContextMenus // Set the context menu item count const int contextMenuItemCountAtkValueIndex = 0; var contextMenuItemCountAtkValue = &m_AtkValues[contextMenuItemCountAtkValueIndex]; - contextMenuItemCountAtkValue->UInt = (uint)contextMenuItems.Count(); + contextMenuItemCountAtkValue->UInt = (uint)contextMenuOpenedArgs.ContextMenuItems.Count(); // Clear the previous arrow flags var hasPreviousArrowAtkValue = &m_AtkValues[HasPreviousArrowFlagsIndex]; @@ -334,9 +334,9 @@ namespace PlayerTags.GameInterface.ContextMenus var subContextMenusFlagsAtkValue = &m_AtkValues[HasNextArrowFlagsIndex]; subContextMenusFlagsAtkValue->UInt = 0; - for (int contextMenuItemIndex = 0; contextMenuItemIndex < contextMenuItems.Count(); ++contextMenuItemIndex) + for (int contextMenuItemIndex = 0; contextMenuItemIndex < contextMenuOpenedArgs.ContextMenuItems.Count(); ++contextMenuItemIndex) { - var contextMenuItem = contextMenuItems.ElementAt(contextMenuItemIndex); + var contextMenuItem = contextMenuOpenedArgs.ContextMenuItems.ElementAt(contextMenuItemIndex); var contextMenuItemAtkValueBaseIndex = FirstContextMenuItemIndex + (contextMenuItemIndex * SequentialAtkValuesPerContextMenuItem); diff --git a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs index 863cc2c..8d6e404 100644 --- a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs +++ b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs @@ -4,12 +4,12 @@ namespace PlayerTags.GameInterface.ContextMenus { public class CustomContextMenuItem : ContextMenuItem { - public CustomContextMenuItemSelectedDelegate CustomAction { get; } + public CustomContextMenuItemSelectedDelegate ItemSelected { get; } - internal CustomContextMenuItem(SeString name, CustomContextMenuItemSelectedDelegate customAction) + internal CustomContextMenuItem(SeString name, CustomContextMenuItemSelectedDelegate itemSelected) : base(name) { - CustomAction = customAction; + ItemSelected = itemSelected; } } } \ No newline at end of file diff --git a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs index 45abfa4..5cca9d4 100644 --- a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs +++ b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs @@ -1,9 +1,18 @@ namespace PlayerTags.GameInterface.ContextMenus { + /// + /// Provides data for events. + /// public class CustomContextMenuItemSelectedArgs { + /// + /// The currently opened context menu. + /// public ContextMenuOpenedArgs ContextMenuOpenedArgs { get; init; } + /// + /// The selected item within the currently opened context menu. + /// public CustomContextMenuItem SelectedItem { get; init; } public CustomContextMenuItemSelectedArgs(ContextMenuOpenedArgs contextMenuOpenedArgs, CustomContextMenuItem selectedItem) diff --git a/PlayerTags/GameInterface/GameInterfaceHelper.cs b/PlayerTags/GameInterface/GameInterfaceHelper.cs index 46568f1..2fc710a 100644 --- a/PlayerTags/GameInterface/GameInterfaceHelper.cs +++ b/PlayerTags/GameInterface/GameInterfaceHelper.cs @@ -74,10 +74,8 @@ namespace PlayerTags.GameInterface return true; } - public static IntPtr PluginAllocate(SeString seString) + public static IntPtr PluginAllocate(byte[] bytes) { - var bytes = seString.Encode(); - IntPtr pointer = Marshal.AllocHGlobal(bytes.Length + 1); Marshal.Copy(bytes, 0, pointer, bytes.Length); Marshal.WriteByte(pointer, bytes.Length, 0); @@ -85,6 +83,11 @@ namespace PlayerTags.GameInterface return pointer; } + public static IntPtr PluginAllocate(SeString seString) + { + return PluginAllocate(seString.Encode()); + } + public static void PluginFree(ref IntPtr ptr) { Marshal.FreeHGlobal(ptr); diff --git a/PlayerTags/GameInterface/Nameplates/Nameplate.cs b/PlayerTags/GameInterface/Nameplates/Nameplate.cs index ff8f1cd..ecd3add 100644 --- a/PlayerTags/GameInterface/Nameplates/Nameplate.cs +++ b/PlayerTags/GameInterface/Nameplates/Nameplate.cs @@ -7,6 +7,7 @@ using Dalamud.Logging; using FFXIVClientStructs.FFXIV.Client.UI; using System; using System.Runtime.InteropServices; +using System.Linq; namespace PlayerTags.GameInterface.Nameplates { @@ -97,34 +98,38 @@ namespace PlayerTags.GameInterface.Nameplates isTitleAboveName, iconId); - var beforeNameHashCode = playerNameplateUpdatedArgs.Name.GetHashCode(); - var beforeTitleHashCode = playerNameplateUpdatedArgs.Title.GetHashCode(); - var beforeFreeCompanyHashCode = playerNameplateUpdatedArgs.FreeCompany.GetHashCode(); + byte[] beforeNameBytes = playerNameplateUpdatedArgs.Name.Encode(); + byte[] beforeTitleBytes = playerNameplateUpdatedArgs.Title.Encode(); + byte[] beforeFreeCompanyBytes = playerNameplateUpdatedArgs.FreeCompany.Encode(); PlayerNameplateUpdated?.Invoke(playerNameplateUpdatedArgs); + byte[] afterNameBytes = playerNameplateUpdatedArgs.Name.Encode(); + byte[] afterTitleBytes = playerNameplateUpdatedArgs.Title.Encode(); + byte[] afterFreeCompanyBytes = playerNameplateUpdatedArgs.FreeCompany.Encode(); + IntPtr newNamePtr = namePtr; - bool hasNameChanged = beforeNameHashCode != playerNameplateUpdatedArgs.Name.GetHashCode(); + bool hasNameChanged = !beforeNameBytes.SequenceEqual(afterNameBytes); if (hasNameChanged) { - newNamePtr = GameInterfaceHelper.PluginAllocate(playerNameplateUpdatedArgs.Name); + newNamePtr = GameInterfaceHelper.PluginAllocate(afterNameBytes); } IntPtr newTitlePtr = titlePtr; - bool hasTitleChanged = beforeTitleHashCode != playerNameplateUpdatedArgs.Title.GetHashCode(); + bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(afterTitleBytes); if (hasTitleChanged) { - newTitlePtr = GameInterfaceHelper.PluginAllocate(playerNameplateUpdatedArgs.Title); + newTitlePtr = GameInterfaceHelper.PluginAllocate(afterTitleBytes); } IntPtr newFreeCompanyPtr = freeCompanyPtr; - bool hasFreeCompanyChanged = beforeFreeCompanyHashCode != playerNameplateUpdatedArgs.FreeCompany.GetHashCode(); + bool hasFreeCompanyChanged = !beforeFreeCompanyBytes.SequenceEqual(afterFreeCompanyBytes); if (hasFreeCompanyChanged) { - newFreeCompanyPtr = GameInterfaceHelper.PluginAllocate(playerNameplateUpdatedArgs.FreeCompany); + newFreeCompanyPtr = GameInterfaceHelper.PluginAllocate(afterFreeCompanyBytes); } - var result = m_SetPlayerNameplateHook.Original(playerNameplateObjectPtr, playerNameplateUpdatedArgs.IsTitleAboveName, playerNameplateUpdatedArgs.IsTitleVisible, newNamePtr, newTitlePtr, newFreeCompanyPtr, playerNameplateUpdatedArgs.IconId); + var result = m_SetPlayerNameplateHook.Original(playerNameplateObjectPtr, playerNameplateUpdatedArgs.IsTitleAboveName, playerNameplateUpdatedArgs.IsTitleVisible, newTitlePtr, newNamePtr, newFreeCompanyPtr, playerNameplateUpdatedArgs.IconId); if (hasNameChanged) {