some work
This commit is contained in:
@@ -15,11 +15,6 @@ namespace PlayerTags.Configuration
|
||||
public int Version { get; set; } = 0;
|
||||
public bool IsVisible = false;
|
||||
|
||||
private const NameplateFreeCompanyVisibility DefaultNameplateFreeCompanyVisibility = Data.NameplateFreeCompanyVisibility.Default;
|
||||
private const NameplateTitleVisibility DefaultNameplateTitleVisibility = Data.NameplateTitleVisibility.WhenHasTags;
|
||||
private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName;
|
||||
private const bool DefaultIsApplyTagsToAllChatMessagesEnabled = true;
|
||||
|
||||
[Obsolete]
|
||||
[JsonProperty("GeneralOptions")]
|
||||
private Dictionary<Data.ActivityContext, GeneralOptionsClass> GeneralOptionsV1
|
||||
|
||||
@@ -4,7 +4,9 @@ using Dalamud.Hooking;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using Pilz.Dalamud.Nameplates;
|
||||
using System;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -15,9 +17,7 @@ namespace PlayerTags.GameInterface.Nameplates
|
||||
/// </summary>
|
||||
public class Nameplate : IDisposable
|
||||
{
|
||||
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))]
|
||||
private readonly Hook<AddonNamePlate_SetPlayerNameplateDetour>? hook_AddonNamePlate_SetPlayerNameplateDetour = null;
|
||||
private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId);
|
||||
public NameplateManager NameplateManager { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a player nameplate is updated by the game.
|
||||
@@ -29,140 +29,37 @@ namespace PlayerTags.GameInterface.Nameplates
|
||||
/// </summary>
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return hook_AddonNamePlate_SetPlayerNameplateDetour != null
|
||||
&& hook_AddonNamePlate_SetPlayerNameplateDetour.IsEnabled;
|
||||
}
|
||||
get => NameplateManager != null && NameplateManager.IsValid;
|
||||
}
|
||||
|
||||
public Nameplate()
|
||||
{
|
||||
SignatureHelper.Initialise(this);
|
||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Enable();
|
||||
NameplateManager = new();
|
||||
NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged += Hooks_AddonNamePlate_SetPlayerNameManaged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Disable();
|
||||
NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged -= Hooks_AddonNamePlate_SetPlayerNameManaged;
|
||||
NameplateManager.Dispose();
|
||||
}
|
||||
|
||||
private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId)
|
||||
private void Hooks_AddonNamePlate_SetPlayerNameManaged(Pilz.Dalamud.Nameplates.EventArgs.AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs)
|
||||
{
|
||||
if (hook_AddonNamePlate_SetPlayerNameplateDetour == null)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PlayerCharacter? playerCharacter = GetNameplateGameObject<PlayerCharacter>(playerNameplateObjectPtr);
|
||||
PlayerCharacter? playerCharacter = NameplateManager.GetNameplateGameObject<PlayerCharacter>(eventArgs.SafeNameplateObject);
|
||||
|
||||
if (playerCharacter != null)
|
||||
{
|
||||
PlayerNameplateUpdatedArgs playerNameplateUpdatedArgs = new PlayerNameplateUpdatedArgs(
|
||||
playerCharacter,
|
||||
GameInterfaceHelper.ReadSeString(namePtr),
|
||||
GameInterfaceHelper.ReadSeString(titlePtr),
|
||||
GameInterfaceHelper.ReadSeString(freeCompanyPtr),
|
||||
isTitleVisible,
|
||||
isTitleAboveName,
|
||||
iconId);
|
||||
|
||||
byte[] beforeNameBytes = playerNameplateUpdatedArgs.Name.Encode();
|
||||
byte[] beforeTitleBytes = playerNameplateUpdatedArgs.Title.Encode();
|
||||
byte[] beforeFreeCompanyBytes = playerNameplateUpdatedArgs.FreeCompany.Encode();
|
||||
|
||||
var playerNameplateUpdatedArgs = new PlayerNameplateUpdatedArgs(playerCharacter, eventArgs);
|
||||
PlayerNameplateUpdated?.Invoke(playerNameplateUpdatedArgs);
|
||||
|
||||
byte[] afterNameBytes = playerNameplateUpdatedArgs.Name.Encode();
|
||||
byte[] afterTitleBytes = playerNameplateUpdatedArgs.Title.Encode();
|
||||
byte[] afterFreeCompanyBytes = playerNameplateUpdatedArgs.FreeCompany.Encode();
|
||||
|
||||
IntPtr newNamePtr = namePtr;
|
||||
bool hasNameChanged = !beforeNameBytes.SequenceEqual(afterNameBytes);
|
||||
if (hasNameChanged)
|
||||
{
|
||||
newNamePtr = GameInterfaceHelper.PluginAllocate(afterNameBytes);
|
||||
}
|
||||
|
||||
IntPtr newTitlePtr = titlePtr;
|
||||
bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(afterTitleBytes);
|
||||
if (hasTitleChanged)
|
||||
{
|
||||
newTitlePtr = GameInterfaceHelper.PluginAllocate(afterTitleBytes);
|
||||
}
|
||||
|
||||
IntPtr newFreeCompanyPtr = freeCompanyPtr;
|
||||
bool hasFreeCompanyChanged = !beforeFreeCompanyBytes.SequenceEqual(afterFreeCompanyBytes);
|
||||
if (hasFreeCompanyChanged)
|
||||
{
|
||||
newFreeCompanyPtr = GameInterfaceHelper.PluginAllocate(afterFreeCompanyBytes);
|
||||
}
|
||||
|
||||
var result = hook_AddonNamePlate_SetPlayerNameplateDetour.Original(playerNameplateObjectPtr, playerNameplateUpdatedArgs.IsTitleAboveName, playerNameplateUpdatedArgs.IsTitleVisible, newTitlePtr, newNamePtr, newFreeCompanyPtr, playerNameplateUpdatedArgs.IconId);
|
||||
|
||||
if (hasNameChanged)
|
||||
{
|
||||
GameInterfaceHelper.PluginFree(ref newNamePtr);
|
||||
}
|
||||
|
||||
if (hasTitleChanged)
|
||||
{
|
||||
GameInterfaceHelper.PluginFree(ref newTitlePtr);
|
||||
}
|
||||
|
||||
if (hasFreeCompanyChanged)
|
||||
{
|
||||
GameInterfaceHelper.PluginFree(ref newFreeCompanyPtr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"SetPlayerNameplateDetour");
|
||||
}
|
||||
|
||||
return hook_AddonNamePlate_SetPlayerNameplateDetour.Original(playerNameplateObjectPtr, isTitleAboveName, isTitleVisible, titlePtr, namePtr, freeCompanyPtr, iconId);
|
||||
}
|
||||
|
||||
private T? GetNameplateGameObject<T>(IntPtr nameplateObjectPtr)
|
||||
where T : GameObject
|
||||
{
|
||||
// Get the nameplate object array
|
||||
var nameplateAddonPtr = PluginServices.GameGui.GetAddonByName("NamePlate", 1);
|
||||
var nameplateObjectArrayPtrPtr = nameplateAddonPtr + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32();
|
||||
var nameplateObjectArrayPtr = Marshal.ReadIntPtr(nameplateObjectArrayPtrPtr);
|
||||
if (nameplateObjectArrayPtr == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Determine the index of the nameplate object within the nameplate object array
|
||||
var namePlateObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject));
|
||||
var namePlateObjectPtr0 = nameplateObjectArrayPtr + namePlateObjectSize * 0;
|
||||
var namePlateIndex = (nameplateObjectPtr.ToInt64() - namePlateObjectPtr0.ToInt64()) / namePlateObjectSize;
|
||||
if (namePlateIndex < 0 || namePlateIndex >= AddonNamePlate.NumNamePlateObjects)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the nameplate info array
|
||||
IntPtr nameplateInfoArrayPtr = IntPtr.Zero;
|
||||
unsafe
|
||||
{
|
||||
var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance();
|
||||
nameplateInfoArrayPtr = new IntPtr(&framework->GetUiModule()->GetRaptureAtkModule()->NamePlateInfoArray);
|
||||
}
|
||||
|
||||
// Get the nameplate info for the nameplate object
|
||||
var namePlateInfoPtr = new IntPtr(nameplateInfoArrayPtr.ToInt64() + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * namePlateIndex);
|
||||
RaptureAtkModule.NamePlateInfo namePlateInfo = Marshal.PtrToStructure<RaptureAtkModule.NamePlateInfo>(namePlateInfoPtr);
|
||||
|
||||
// Return the object for its object id
|
||||
var objectId = namePlateInfo.ObjectID.ObjectID;
|
||||
return PluginServices.ObjectTable.SearchById(objectId) as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,52 @@
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
namespace PlayerTags.GameInterface.Nameplates
|
||||
{
|
||||
public class PlayerNameplateUpdatedArgs
|
||||
{
|
||||
private readonly AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs;
|
||||
|
||||
public PlayerCharacter PlayerCharacter { get; }
|
||||
|
||||
public SeString Name { get; }
|
||||
public SeString Name
|
||||
{
|
||||
get => eventArgs.Name;
|
||||
}
|
||||
|
||||
public SeString Title { get; }
|
||||
public SeString Title
|
||||
{
|
||||
get => eventArgs.Title;
|
||||
}
|
||||
|
||||
public SeString FreeCompany { get; }
|
||||
public SeString FreeCompany
|
||||
{
|
||||
get => eventArgs.FreeCompany;
|
||||
}
|
||||
|
||||
public bool IsTitleVisible { get; set; }
|
||||
public bool IsTitleVisible
|
||||
{
|
||||
get => eventArgs.IsTitleVisible;
|
||||
set => eventArgs.IsTitleVisible = value;
|
||||
}
|
||||
|
||||
public bool IsTitleAboveName { get; set; }
|
||||
public bool IsTitleAboveName
|
||||
{
|
||||
get => eventArgs.IsTitleAboveName;
|
||||
set => eventArgs.IsTitleAboveName = value;
|
||||
}
|
||||
|
||||
public int IconId { get; set; }
|
||||
public int IconId
|
||||
{
|
||||
get => eventArgs.IconID;
|
||||
set => eventArgs.IconID = value;
|
||||
}
|
||||
|
||||
public PlayerNameplateUpdatedArgs(PlayerCharacter playerCharacter, SeString name, SeString title, SeString freeCompany, bool isTitleVisible, bool isTitleAboveName, int iconId)
|
||||
public PlayerNameplateUpdatedArgs(PlayerCharacter playerCharacter, AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs)
|
||||
{
|
||||
PlayerCharacter = playerCharacter;
|
||||
Name = name;
|
||||
Title = title;
|
||||
FreeCompany = freeCompany;
|
||||
IsTitleVisible = isTitleVisible;
|
||||
IsTitleAboveName = isTitleAboveName;
|
||||
IconId = iconId;
|
||||
this.eventArgs = eventArgs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user