some work

This commit is contained in:
2022-11-05 20:27:23 +01:00
parent d38d974aa6
commit 6644b1edb8
3 changed files with 44 additions and 133 deletions

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}