migrate to new api & remove nameplate feature
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Model;
|
||||
namespace Pilz.Dalamud.Icons;
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum StatusIcons
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
public class AddonNamePlate_SetPlayerNameEventArgs : HookWithResultBaseEventArgs<IntPtr>
|
||||
{
|
||||
public IntPtr PlayerNameplateObjectPtr { get; set; }
|
||||
public IntPtr TitlePtr { get; set; }
|
||||
public IntPtr NamePtr { get; set; }
|
||||
public IntPtr FreeCompanyPtr { get; set; }
|
||||
public IntPtr PrefixPtr { get; set; }
|
||||
public bool IsTitleAboveName { get; set; }
|
||||
public bool IsTitleVisible { get; set; }
|
||||
public int IconID { get; set; }
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
public class AddonNamePlate_SetPlayerNameManagedEventArgs : HookWithResultManagedBaseEventArgs<IntPtr>
|
||||
{
|
||||
public new AddonNamePlate_SetPlayerNameEventArgs OriginalEventArgs
|
||||
{
|
||||
get => base.OriginalEventArgs as AddonNamePlate_SetPlayerNameEventArgs;
|
||||
set => base.OriginalEventArgs = value;
|
||||
}
|
||||
|
||||
public SafeNameplateObject SafeNameplateObject { get; set; }
|
||||
public SeString Title { get; internal set; }
|
||||
public SeString Name { get; internal set; }
|
||||
public SeString FreeCompany { get; internal set; }
|
||||
public SeString Prefix { get; internal set; }
|
||||
|
||||
public bool IsTitleAboveName
|
||||
{
|
||||
get => OriginalEventArgs.IsTitleAboveName;
|
||||
set => OriginalEventArgs.IsTitleAboveName = value;
|
||||
}
|
||||
|
||||
public bool IsTitleVisible
|
||||
{
|
||||
get => OriginalEventArgs.IsTitleVisible;
|
||||
set => OriginalEventArgs.IsTitleVisible = value;
|
||||
}
|
||||
|
||||
public int IconID
|
||||
{
|
||||
get => OriginalEventArgs.IconID;
|
||||
set => OriginalEventArgs.IconID = value;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
public abstract class HookBaseEventArgs
|
||||
{
|
||||
internal event Action CallOriginal;
|
||||
|
||||
public void Original()
|
||||
{
|
||||
CallOriginal?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
public abstract class HookManagedBaseEventArgs
|
||||
{
|
||||
public HookBaseEventArgs OriginalEventArgs { get; internal set; }
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
public abstract class HookWithResultBaseEventArgs<TResult>
|
||||
{
|
||||
internal event Func<TResult> CallOriginal;
|
||||
|
||||
public TResult Result { get; set; }
|
||||
|
||||
// Call Original based on the given properties
|
||||
public TResult Original()
|
||||
{
|
||||
return CallOriginal.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Pilz.Dalamud.Nameplates.EventArgs;
|
||||
|
||||
public abstract class HookWithResultManagedBaseEventArgs<TResult>
|
||||
{
|
||||
public HookWithResultBaseEventArgs<TResult> OriginalEventArgs { get; internal set; }
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Model;
|
||||
|
||||
public class SafeAddonNameplate
|
||||
{
|
||||
private readonly DalamudPluginInterface Interface;
|
||||
|
||||
public IntPtr Pointer => PluginServices.GameGui.GetAddonByName("NamePlate", 1);
|
||||
|
||||
public SafeAddonNameplate(DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
Interface = pluginInterface;
|
||||
}
|
||||
|
||||
public unsafe SafeNameplateObject GetNamePlateObject(int index)
|
||||
{
|
||||
SafeNameplateObject result = null;
|
||||
|
||||
if (Pointer != IntPtr.Zero)
|
||||
{
|
||||
var npObjectArrayPtrPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32();
|
||||
var npObjectArrayPtr = Marshal.ReadIntPtr(npObjectArrayPtrPtr);
|
||||
|
||||
if (npObjectArrayPtr != IntPtr.Zero)
|
||||
{
|
||||
var npObjectPtr = npObjectArrayPtr + Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject)) * index;
|
||||
result = new(npObjectPtr, index);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Model;
|
||||
|
||||
public class SafeNameplateInfo
|
||||
{
|
||||
public readonly IntPtr Pointer;
|
||||
public readonly RaptureAtkModule.NamePlateInfo Data;
|
||||
|
||||
public SafeNameplateInfo(IntPtr pointer)
|
||||
{
|
||||
Pointer = pointer;
|
||||
Data = Marshal.PtrToStructure<RaptureAtkModule.NamePlateInfo>(Pointer);
|
||||
}
|
||||
|
||||
internal IntPtr NameAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.Name));
|
||||
internal IntPtr FcNameAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.FcName));
|
||||
internal IntPtr TitleAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.Title));
|
||||
internal IntPtr DisplayTitleAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.DisplayTitle));
|
||||
internal IntPtr LevelTextAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.LevelText));
|
||||
|
||||
public string Name => GetString(NameAddress);
|
||||
public string FcName => GetString(FcNameAddress);
|
||||
public string Title => GetString(TitleAddress);
|
||||
public string DisplayTitle => GetString(DisplayTitleAddress);
|
||||
public string LevelText => GetString(LevelTextAddress);
|
||||
|
||||
//public bool IsPlayerCharacter() => XivApi.IsPlayerCharacter(Data.ObjectID.ObjectID);
|
||||
|
||||
//public bool IsPartyMember() => XivApi.IsPartyMember(Data.ObjectID.ObjectID);
|
||||
|
||||
//public bool IsAllianceMember() => XivApi.IsAllianceMember(Data.ObjectID.ObjectID);
|
||||
|
||||
//public uint GetJobID() => GetJobId(Data.ObjectID.ObjectID);
|
||||
|
||||
private unsafe IntPtr GetStringPtr(string name)
|
||||
{
|
||||
var namePtr = Pointer + Marshal.OffsetOf(typeof(RaptureAtkModule.NamePlateInfo), name).ToInt32();
|
||||
var stringPtrPtr = namePtr + Marshal.OffsetOf(typeof(Utf8String), nameof(Utf8String.StringPtr)).ToInt32();
|
||||
var stringPtr = Marshal.ReadIntPtr(stringPtrPtr);
|
||||
return stringPtr;
|
||||
}
|
||||
|
||||
private string GetString(IntPtr stringPtr)
|
||||
{
|
||||
return Marshal.PtrToStringUTF8(stringPtr);
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Model;
|
||||
|
||||
public class SafeNameplateObject
|
||||
{
|
||||
public IntPtr Pointer { get; }
|
||||
public AddonNamePlate.NamePlateObject Data { get; }
|
||||
|
||||
private int _Index;
|
||||
private SafeNameplateInfo _NamePlateInfo;
|
||||
|
||||
public SafeNameplateObject(IntPtr pointer, int index = -1)
|
||||
{
|
||||
Pointer = pointer;
|
||||
Data = Marshal.PtrToStructure<AddonNamePlate.NamePlateObject>(pointer);
|
||||
_Index = index;
|
||||
}
|
||||
|
||||
public int Index
|
||||
{
|
||||
get
|
||||
{
|
||||
int result = _Index;
|
||||
|
||||
if (_Index == -1)
|
||||
{
|
||||
var addon = XivApi.GetSafeAddonNamePlate();
|
||||
var npObject0 = addon.GetNamePlateObject(0);
|
||||
|
||||
if (npObject0 == null)
|
||||
result = -1; // NamePlateObject0 was null
|
||||
else
|
||||
{
|
||||
var npObjectBase = npObject0.Pointer;
|
||||
var npObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject));
|
||||
var index = (Pointer.ToInt64() - npObjectBase.ToInt64()) / npObjectSize;
|
||||
|
||||
if (index < 0 || index >= 50)
|
||||
result = -2; // NamePlateObject index was out of bounds
|
||||
else
|
||||
result = _Index = (int)index;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public SafeNameplateInfo NamePlateInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
SafeNameplateInfo result = null;
|
||||
|
||||
if (_NamePlateInfo != null)
|
||||
{
|
||||
var rapturePtr = XivApi.RaptureAtkModulePtr;
|
||||
|
||||
if (rapturePtr != IntPtr.Zero)
|
||||
{
|
||||
var npInfoArrayPtr = rapturePtr + Marshal.OffsetOf(typeof(RaptureAtkModule), nameof(RaptureAtkModule.NamePlateInfoArray)).ToInt32();
|
||||
var npInfoPtr = npInfoArrayPtr + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * Index;
|
||||
result = _NamePlateInfo = new SafeNameplateInfo(npInfoPtr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#region Getters
|
||||
|
||||
public unsafe IntPtr IconImageNodeAddress => Marshal.ReadIntPtr(Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconImageNode)).ToInt32());
|
||||
public unsafe IntPtr NameNodeAddress => Marshal.ReadIntPtr(Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.NameText)).ToInt32());
|
||||
|
||||
public AtkImageNode IconImageNode => Marshal.PtrToStructure<AtkImageNode>(IconImageNodeAddress);
|
||||
public AtkTextNode NameTextNode => Marshal.PtrToStructure<AtkTextNode>(NameNodeAddress);
|
||||
|
||||
#endregion
|
||||
|
||||
public unsafe bool IsVisible => Data.IsVisible;
|
||||
public unsafe bool IsLocalPlayer => Data.IsLocalPlayer;
|
||||
public bool IsPlayer => Data.NameplateKind == 0;
|
||||
|
||||
//public void SetIconScale(float scale, bool force = false)
|
||||
//{
|
||||
// if (force || IconImageNode.AtkResNode.ScaleX != scale || IconImageNode.AtkResNode.ScaleY != scale)
|
||||
// {
|
||||
// Instance.SetNodeScale(IconImageNodeAddress, scale, scale);
|
||||
// }
|
||||
//}
|
||||
|
||||
//public void SetNameScale(float scale, bool force = false)
|
||||
//{
|
||||
// if (force || NameTextNode.AtkResNode.ScaleX != scale || NameTextNode.AtkResNode.ScaleY != scale)
|
||||
// {
|
||||
// Instance.SetNodeScale(NameNodeAddress, scale, scale);
|
||||
// }
|
||||
//}
|
||||
|
||||
//public unsafe void SetName(IntPtr ptr)
|
||||
//{
|
||||
// NameTextNode.SetText("aaa");
|
||||
//}
|
||||
|
||||
//public void SetIcon(int icon)
|
||||
//{
|
||||
// IconImageNode.LoadIconTexture(icon, 1);
|
||||
//}
|
||||
|
||||
public void SetIconPosition(short x, short y)
|
||||
{
|
||||
var iconXAdjustPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconXAdjust)).ToInt32();
|
||||
var iconYAdjustPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconYAdjust)).ToInt32();
|
||||
Marshal.WriteInt16(iconXAdjustPtr, x);
|
||||
Marshal.WriteInt16(iconYAdjustPtr, y);
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using Pilz.Dalamud.Nameplates.EventArgs;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates;
|
||||
|
||||
public class NameplateHooks : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Will be executed when the the Game wants to update the content of a nameplate with the details of the Player.
|
||||
/// </summary>
|
||||
public event AddonNamePlate_SetPlayerNameEventHandler AddonNamePlate_SetPlayerName;
|
||||
public delegate void AddonNamePlate_SetPlayerNameEventHandler(AddonNamePlate_SetPlayerNameEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Will be executed when the the Game wants to update the content of a nameplate with the details of the Player.
|
||||
/// This will event acts on a higher level with SeString instead of IntPtr e.g.
|
||||
/// </summary>
|
||||
public event AddonNamePlate_SetPlayerNameManagedEventHandler AddonNamePlate_SetPlayerNameManaged;
|
||||
public delegate void AddonNamePlate_SetPlayerNameManagedEventHandler(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs);
|
||||
|
||||
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 5C 24 ?? 45 38 BE", DetourName = nameof(SetPlayerNameplateDetour))]
|
||||
private 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, IntPtr prefix, int iconId);
|
||||
|
||||
/// <summary>
|
||||
/// Defines if all hooks are enabled. If this is false, then there might be something wrong or the class already has been disposed.
|
||||
/// </summary>
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
var isValid = true;
|
||||
|
||||
isValid &= IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of NAmeplateHooks and automatically initialize and enable all Hooks.
|
||||
/// </summary>
|
||||
public NameplateHooks()
|
||||
{
|
||||
PluginServices.GameInteropProvider.InitializeFromAttributes(this);
|
||||
}
|
||||
|
||||
~NameplateHooks()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Unhook(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize and enable all Hooks.
|
||||
/// </summary>
|
||||
internal void Initialize()
|
||||
{
|
||||
if (!IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour))
|
||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Enable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable all Hooks.
|
||||
/// </summary>
|
||||
internal void Unhook()
|
||||
{
|
||||
Unhook(false);
|
||||
}
|
||||
|
||||
private void Unhook(bool isDisposing)
|
||||
{
|
||||
if (isDisposing)
|
||||
{
|
||||
if (!IsHookDisposed(hook_AddonNamePlate_SetPlayerNameplateDetour))
|
||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour))
|
||||
hook_AddonNamePlate_SetPlayerNameplateDetour?.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsHookDisposed<T>(Hook<T> hook) where T : Delegate
|
||||
{
|
||||
return hook == null || hook.IsDisposed;
|
||||
}
|
||||
|
||||
private static bool IsHookEnabled<T>(Hook<T> hook) where T : Delegate
|
||||
{
|
||||
return !IsHookDisposed(hook) && hook.IsEnabled;
|
||||
}
|
||||
|
||||
private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, IntPtr prefix, int iconId)
|
||||
{
|
||||
var result = IntPtr.Zero;
|
||||
|
||||
if (IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour))
|
||||
{
|
||||
var eventArgs = new AddonNamePlate_SetPlayerNameEventArgs
|
||||
{
|
||||
PlayerNameplateObjectPtr = playerNameplateObjectPtr,
|
||||
TitlePtr = titlePtr,
|
||||
NamePtr = namePtr,
|
||||
FreeCompanyPtr = freeCompanyPtr,
|
||||
PrefixPtr = prefix,
|
||||
IsTitleAboveName = isTitleAboveName,
|
||||
IsTitleVisible = isTitleVisible,
|
||||
IconID = iconId
|
||||
};
|
||||
|
||||
void callOriginal()
|
||||
{
|
||||
eventArgs.Result = eventArgs.Original();
|
||||
}
|
||||
|
||||
// Add handler for the Original call
|
||||
eventArgs.CallOriginal += () =>
|
||||
{
|
||||
return hook_AddonNamePlate_SetPlayerNameplateDetour.Original(
|
||||
eventArgs.PlayerNameplateObjectPtr,
|
||||
eventArgs.IsTitleAboveName,
|
||||
eventArgs.IsTitleVisible,
|
||||
eventArgs.TitlePtr,
|
||||
eventArgs.NamePtr,
|
||||
eventArgs.FreeCompanyPtr,
|
||||
prefix,
|
||||
eventArgs.IconID);
|
||||
};
|
||||
|
||||
// Invoke Event
|
||||
var hasDefaultHookEvent = AddonNamePlate_SetPlayerName != null;
|
||||
AddonNamePlate_SetPlayerName?.Invoke(eventArgs);
|
||||
|
||||
if (AddonNamePlate_SetPlayerNameManaged != null)
|
||||
{
|
||||
var freeTitle = false;
|
||||
var freeName = false;
|
||||
var freeFreeCompany = false;
|
||||
var freePrefix = false;
|
||||
|
||||
// Create NamePlateObject if possible
|
||||
var namePlateObj = new SafeNameplateObject(playerNameplateObjectPtr);
|
||||
|
||||
// Create new event
|
||||
var managedEventArgs = new AddonNamePlate_SetPlayerNameManagedEventArgs
|
||||
{
|
||||
OriginalEventArgs = eventArgs,
|
||||
SafeNameplateObject = namePlateObj,
|
||||
Title = GameInterfaceHelper.ReadSeString(eventArgs.TitlePtr),
|
||||
Name = GameInterfaceHelper.ReadSeString(eventArgs.NamePtr),
|
||||
FreeCompany = GameInterfaceHelper.ReadSeString(eventArgs.FreeCompanyPtr),
|
||||
Prefix = GameInterfaceHelper.ReadSeString(eventArgs.PrefixPtr)
|
||||
};
|
||||
|
||||
// Get raw string content
|
||||
var titleRaw = managedEventArgs.Title.Encode();
|
||||
var nameRaw = managedEventArgs.Name.Encode();
|
||||
var freeCompanyRaw = managedEventArgs.FreeCompany.Encode();
|
||||
var prefixRaw = managedEventArgs.Prefix.Encode();
|
||||
|
||||
// Invoke Managed Event
|
||||
AddonNamePlate_SetPlayerNameManaged.Invoke(managedEventArgs);
|
||||
|
||||
// Get new Title string content
|
||||
var titleNewRaw = managedEventArgs.Title.Encode();
|
||||
if (!titleRaw.SequenceEqual(titleNewRaw))
|
||||
{
|
||||
eventArgs.TitlePtr = GameInterfaceHelper.PluginAllocate(titleNewRaw);
|
||||
freeTitle = true;
|
||||
}
|
||||
|
||||
// Get new Name string content
|
||||
var nameNewRaw = managedEventArgs.Name.Encode();
|
||||
if (!nameRaw.SequenceEqual(nameNewRaw))
|
||||
{
|
||||
eventArgs.NamePtr = GameInterfaceHelper.PluginAllocate(nameNewRaw);
|
||||
freeName = true;
|
||||
}
|
||||
|
||||
// Get new Free Company string content
|
||||
var freeCompanyNewRaw = managedEventArgs.FreeCompany.Encode();
|
||||
if (!freeCompanyRaw.SequenceEqual(freeCompanyNewRaw))
|
||||
{
|
||||
eventArgs.FreeCompanyPtr = GameInterfaceHelper.PluginAllocate(freeCompanyNewRaw);
|
||||
freeFreeCompany = true;
|
||||
}
|
||||
|
||||
// Get new Prefix string content
|
||||
var prefixNewRaw = managedEventArgs.Prefix.Encode();
|
||||
if (!prefixRaw.SequenceEqual(prefixNewRaw))
|
||||
{
|
||||
eventArgs.PrefixPtr = GameInterfaceHelper.PluginAllocate(prefixNewRaw);
|
||||
freePrefix = true;
|
||||
}
|
||||
|
||||
// Call Original as we changed something
|
||||
callOriginal();
|
||||
|
||||
// Free memory
|
||||
if (freeTitle)
|
||||
GameInterfaceHelper.PluginFree(eventArgs.TitlePtr);
|
||||
if (freeName)
|
||||
GameInterfaceHelper.PluginFree(eventArgs.NamePtr);
|
||||
if (freeFreeCompany)
|
||||
GameInterfaceHelper.PluginFree(eventArgs.FreeCompanyPtr);
|
||||
if (freePrefix)
|
||||
GameInterfaceHelper.PluginFree(eventArgs.PrefixPtr);
|
||||
}
|
||||
else if (!hasDefaultHookEvent)
|
||||
{
|
||||
// Call original in case of nothing get called, just to get secure it will not break the game when not calling it.
|
||||
callOriginal();
|
||||
}
|
||||
|
||||
// Set result
|
||||
result = eventArgs.Result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates;
|
||||
|
||||
public class NameplateManager : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides events that you can hook to.
|
||||
/// </summary>
|
||||
public NameplateHooks Hooks { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Defines if all hooks are enabled and the NameplateManager is ready to go. If this is false, then there might be something wrong or something already has been disposed.
|
||||
/// </summary>
|
||||
public bool IsValid => Hooks.IsValid;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the NameplateManager.
|
||||
/// </summary>
|
||||
public NameplateManager()
|
||||
{
|
||||
Hooks.Initialize();
|
||||
}
|
||||
|
||||
~NameplateManager()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Hooks?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public static T? GetNameplateGameObject<T>(SafeNameplateObject namePlateObject) where T : GameObject
|
||||
{
|
||||
return GetNameplateGameObject<T>(namePlateObject.Pointer);
|
||||
}
|
||||
|
||||
public static 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,54 +0,0 @@
|
||||
using Pilz.Dalamud.Nameplates.EventArgs;
|
||||
using Pilz.Dalamud.Tools.Strings;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
|
||||
public class NameplateChanges
|
||||
{
|
||||
private readonly Dictionary<NameplateElements, StringChangesProps> changes = [];
|
||||
|
||||
public NameplateChanges()
|
||||
{
|
||||
changes.Add(NameplateElements.Title, new());
|
||||
changes.Add(NameplateElements.Name, new());
|
||||
changes.Add(NameplateElements.FreeCompany, new());
|
||||
}
|
||||
|
||||
public NameplateChanges(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs) : this()
|
||||
{
|
||||
GetProps(NameplateElements.Title).Destination = eventArgs.Title;
|
||||
GetProps(NameplateElements.Name).Destination = eventArgs.Name;
|
||||
GetProps(NameplateElements.FreeCompany).Destination = eventArgs.FreeCompany;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options.
|
||||
/// </summary>
|
||||
/// <param name="element">The position of your choice.</param>
|
||||
/// <returns></returns>
|
||||
public StringChangesProps GetProps(NameplateElements element)
|
||||
{
|
||||
return changes[element];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the changes of an element of your choice where you can add your payloads to a change.
|
||||
/// </summary>
|
||||
/// <param name="element">The position of your choice.</param>
|
||||
/// <returns></returns>
|
||||
public StringChanges GetChanges(NameplateElements element)
|
||||
{
|
||||
return GetProps(element).StringChanges;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a change of the position of the element of your choice where you can add your payloads.
|
||||
/// </summary>
|
||||
/// <param name="element">The position of your choice.</param>
|
||||
/// <param name="position">The position of your choice.</param>
|
||||
/// <returns></returns>
|
||||
public StringChange GetChange(NameplateElements element, StringPosition position)
|
||||
{
|
||||
return GetChanges(element).GetChange(position);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
|
||||
public enum NameplateElements
|
||||
{
|
||||
Name,
|
||||
Title,
|
||||
FreeCompany
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Pilz.Dalamud.ActivityContexts;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
using Pilz.Dalamud.Tools;
|
||||
using Pilz.Dalamud.Tools.Strings;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
|
||||
public static class NameplateUpdateFactory
|
||||
{
|
||||
public static void ApplyNameplateChanges(NameplateChangesProps props)
|
||||
{
|
||||
foreach (NameplateElements element in Enum.GetValues(typeof(NameplateElements)))
|
||||
{
|
||||
var change = props.Changes.GetProps(element);
|
||||
StringUpdateFactory.ApplyStringChanges(change);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ApplyStatusIconWithPrio(ref int statusIcon, int newStatusIcon, StringChange stringChange, ActivityContext activityContext, StatusIconPriorizer priorizer, bool moveIconToNameplateIfPossible)
|
||||
{
|
||||
bool? isPrio = null;
|
||||
var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)statusIcon);
|
||||
|
||||
if (moveIconToNameplateIfPossible)
|
||||
{
|
||||
if (fontIcon != null)
|
||||
{
|
||||
// Set new font icon as string change
|
||||
var iconPayload = new IconPayload(fontIcon.Value);
|
||||
stringChange.Payloads.Insert(0, iconPayload);
|
||||
|
||||
// If we moved it, we don't need it as icon anymore, yay :D
|
||||
isPrio = false;
|
||||
}
|
||||
}
|
||||
|
||||
isPrio ??= priorizer.IsPriorityIcon(statusIcon, activityContext);
|
||||
|
||||
if (!isPrio.Value)
|
||||
statusIcon = newStatusIcon;
|
||||
|
||||
return isPrio.Value;
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,12 @@ namespace Pilz.Dalamud;
|
||||
|
||||
public class PluginServices
|
||||
{
|
||||
[PluginService] public static IDalamudPluginInterface PluginInterface { get; set; } = null;
|
||||
[PluginService] public static IGameGui GameGui { get; set; } = null;
|
||||
[PluginService] public static IClientState ClientState { get; set; } = null;
|
||||
[PluginService] public static IDataManager DataManager { get; set; } = null;
|
||||
[PluginService] public static IObjectTable ObjectTable { get; set; } = null;
|
||||
[PluginService] public static IGameInteropProvider GameInteropProvider { get; set; } = null;
|
||||
[PluginService] public static IDalamudPluginInterface PluginInterface { get; set; }
|
||||
[PluginService] public static IGameGui GameGui { get; set; }
|
||||
[PluginService] public static IClientState ClientState { get; set; }
|
||||
[PluginService] public static IDataManager DataManager { get; set; }
|
||||
[PluginService] public static IObjectTable ObjectTable { get; set; }
|
||||
[PluginService] public static IGameInteropProvider GameInteropProvider { get; set; }
|
||||
|
||||
public static void Initialize(IDalamudPluginInterface dalamudPluginInterface)
|
||||
{
|
||||
|
||||
25
Pilz.Dalamud/Tools/NamePlates/NameplateChanges.cs
Normal file
25
Pilz.Dalamud/Tools/NamePlates/NameplateChanges.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Dalamud.Game.Gui.NamePlate;
|
||||
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public class NameplateChanges
|
||||
{
|
||||
private readonly List<NameplateElementChange> changes = [];
|
||||
|
||||
public NameplateChanges(INamePlateUpdateHandler handler)
|
||||
{
|
||||
changes.Add(new(NameplateElements.Title, handler));
|
||||
changes.Add(new(NameplateElements.Name, handler));
|
||||
changes.Add(new(NameplateElements.FreeCompany, handler));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options.
|
||||
/// </summary>
|
||||
/// <param name="element">The position of your choice.</param>
|
||||
/// <returns></returns>
|
||||
public NameplateElementChange GetChange(NameplateElements element)
|
||||
{
|
||||
return changes.FirstOrDefault(n => n.Element == element);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public class NameplateChangesProps
|
||||
{
|
||||
44
Pilz.Dalamud/Tools/NamePlates/NameplateElementChange.cs
Normal file
44
Pilz.Dalamud/Tools/NamePlates/NameplateElementChange.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Dalamud.Game.Gui.NamePlate;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Pilz.Dalamud.Tools.Strings;
|
||||
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public class NameplateElementChange(NameplateElements element, INamePlateUpdateHandler handler)
|
||||
{
|
||||
public NameplateElements Element => element;
|
||||
public StringChanges Changes { get; set; } = new();
|
||||
|
||||
public void ApplyFormatting(SeString prefix, SeString postfix)
|
||||
{
|
||||
var parts = (prefix, postfix);
|
||||
|
||||
switch (element)
|
||||
{
|
||||
case NameplateElements.Name:
|
||||
handler.NameParts.TextWrap = parts;
|
||||
break;
|
||||
case NameplateElements.Title:
|
||||
handler.TitleParts.TextWrap = parts;
|
||||
break;
|
||||
case NameplateElements.FreeCompany:
|
||||
handler.FreeCompanyTagParts.TextWrap = parts;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyChanges()
|
||||
{
|
||||
StringUpdateFactory.ApplyStringChanges(new()
|
||||
{
|
||||
StringChanges = Changes,
|
||||
Destination = element switch
|
||||
{
|
||||
NameplateElements.Name => handler.NameParts.Text ??= handler.InfoView.Name,
|
||||
NameplateElements.Title => handler.TitleParts.Text ??= handler.InfoView.Title,
|
||||
NameplateElements.FreeCompany => handler.FreeCompanyTagParts.Text ??= handler.InfoView.FreeCompanyTag,
|
||||
_ => null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
8
Pilz.Dalamud/Tools/NamePlates/NameplateElements.cs
Normal file
8
Pilz.Dalamud/Tools/NamePlates/NameplateElements.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public enum NameplateElements
|
||||
{
|
||||
Name,
|
||||
Title,
|
||||
FreeCompany,
|
||||
}
|
||||
48
Pilz.Dalamud/Tools/NamePlates/NameplateUpdateFactory.cs
Normal file
48
Pilz.Dalamud/Tools/NamePlates/NameplateUpdateFactory.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Dalamud.Game.Gui.NamePlate;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Pilz.Dalamud.ActivityContexts;
|
||||
using Pilz.Dalamud.Icons;
|
||||
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public static class NameplateUpdateFactory
|
||||
{
|
||||
public static void ApplyNameplateChanges(NameplateChangesProps props)
|
||||
{
|
||||
foreach (NameplateElements element in Enum.GetValues(typeof(NameplateElements)))
|
||||
{
|
||||
var change = props.Changes.GetChange(element);
|
||||
change.ApplyChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ApplyStatusIconWithPrio(INamePlateUpdateHandler handler, int newStatusIcon, ActivityContext activityContext, StatusIconPriorizer priorizer, bool moveIconToNameplateIfPossible)
|
||||
{
|
||||
bool? isPrio = null;
|
||||
var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)handler.NameIconId);
|
||||
|
||||
if (moveIconToNameplateIfPossible)
|
||||
{
|
||||
if (fontIcon != null)
|
||||
{
|
||||
// Set new font icon as string change
|
||||
var icon = new IconPayload(fontIcon.Value); ;
|
||||
if (handler.StatusPrefix is SeString str)
|
||||
str.Payloads.Insert(0, icon);
|
||||
else
|
||||
handler.StatusPrefix = SeString.Empty.Append(icon);
|
||||
|
||||
// If we moved it, we don't need it as icon anymore, yay :D
|
||||
isPrio = false;
|
||||
}
|
||||
}
|
||||
|
||||
isPrio ??= priorizer.IsPriorityIcon(handler.NameIconId, activityContext);
|
||||
|
||||
if (!isPrio.Value)
|
||||
handler.NameIconId = newStatusIcon;
|
||||
|
||||
return isPrio.Value;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Pilz.Dalamud.ActivityContexts;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
using Pilz.Dalamud.Icons;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public class StatusIconPriorizer
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public enum StatusIconPriorizerConditionSets
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
using Pilz.Dalamud.Icons;
|
||||
|
||||
namespace Pilz.Dalamud.Nameplates.Tools;
|
||||
namespace Pilz.Dalamud.Tools.NamePlates;
|
||||
|
||||
public class StatusIconPriorizerSettings
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
using Pilz.Dalamud.Icons;
|
||||
|
||||
namespace Pilz.Dalamud.Tools;
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
|
||||
namespace Pilz.Dalamud;
|
||||
|
||||
public class XivApi
|
||||
{
|
||||
private static IntPtr _RaptureAtkModulePtr = IntPtr.Zero;
|
||||
|
||||
public static IntPtr RaptureAtkModulePtr
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_RaptureAtkModulePtr == IntPtr.Zero)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var framework = Framework.Instance();
|
||||
var uiModule = framework->GetUiModule();
|
||||
|
||||
_RaptureAtkModulePtr = new IntPtr(uiModule->GetRaptureAtkModule());
|
||||
}
|
||||
}
|
||||
|
||||
return _RaptureAtkModulePtr;
|
||||
}
|
||||
}
|
||||
|
||||
public static SafeAddonNameplate GetSafeAddonNamePlate()
|
||||
{
|
||||
return new(PluginServices.PluginInterface);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user