migrate chat, nameplate, etc. to new api
This commit is contained in:
Submodule Pilz.Dalamud updated: 40c0821283...47932b2883
@@ -2,7 +2,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Pilz.Dalamud.ActivityContexts;
|
||||
using Pilz.Dalamud.Nameplates.Tools;
|
||||
using Pilz.Dalamud.Tools.NamePlates;
|
||||
using PlayerTags.Data;
|
||||
using PlayerTags.Inheritables;
|
||||
using System;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
@@ -6,8 +7,7 @@ using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Pilz.Dalamud.ActivityContexts;
|
||||
using Pilz.Dalamud.Icons;
|
||||
using Pilz.Dalamud.Nameplates.Model;
|
||||
using Pilz.Dalamud.Nameplates.Tools;
|
||||
using Pilz.Dalamud.Tools.NamePlates;
|
||||
using PlayerTags.Data;
|
||||
using PlayerTags.Inheritables;
|
||||
using PlayerTags.PluginStrings;
|
||||
@@ -162,8 +162,8 @@ public class PluginConfigurationUI
|
||||
if (PluginServices.ClientState.LocalPlayer != null)
|
||||
{
|
||||
Dictionary<Identity, PlayerInfo> playerNameContexts = PluginServices.ObjectTable
|
||||
.Where(gameObject => gameObject is PlayerCharacter)
|
||||
.Select(gameObject => gameObject as PlayerCharacter)
|
||||
.Where(gameObject => gameObject is IPlayerCharacter)
|
||||
.Select(gameObject => gameObject as IPlayerCharacter)
|
||||
.ToDictionary(
|
||||
playerCharacter => m_PluginData.GetIdentity(playerCharacter!),
|
||||
playerCharacter => new PlayerInfo()
|
||||
|
||||
@@ -4,5 +4,5 @@ public enum NameplateElement
|
||||
{
|
||||
Name,
|
||||
Title,
|
||||
FreeCompany
|
||||
FreeCompany,
|
||||
}
|
||||
|
||||
@@ -1,37 +1,28 @@
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
|
||||
namespace PlayerTags.Data;
|
||||
|
||||
public static class PlayerContextHelper
|
||||
{
|
||||
public static PlayerContext GetPlayerContext(PlayerCharacter playerCharacter)
|
||||
public static PlayerContext GetPlayerContext(IPlayerCharacter playerCharacter)
|
||||
{
|
||||
PlayerContext playerContext = PlayerContext.None;
|
||||
var playerContext = PlayerContext.None;
|
||||
|
||||
if (PluginServices.ClientState.LocalPlayer == playerCharacter)
|
||||
{
|
||||
playerContext |= PlayerContext.Self;
|
||||
}
|
||||
|
||||
if (playerCharacter.StatusFlags.HasFlag(StatusFlags.Friend))
|
||||
{
|
||||
playerContext |= PlayerContext.Friend;
|
||||
}
|
||||
|
||||
if (playerCharacter.StatusFlags.HasFlag(StatusFlags.PartyMember))
|
||||
{
|
||||
playerContext |= PlayerContext.Party;
|
||||
}
|
||||
|
||||
if (playerCharacter.StatusFlags.HasFlag(StatusFlags.AllianceMember))
|
||||
{
|
||||
playerContext |= PlayerContext.Alliance;
|
||||
}
|
||||
|
||||
if (playerCharacter.StatusFlags.HasFlag(StatusFlags.Hostile))
|
||||
{
|
||||
playerContext |= PlayerContext.Enemy;
|
||||
}
|
||||
|
||||
return playerContext;
|
||||
}
|
||||
@@ -39,40 +30,29 @@ public static class PlayerContextHelper
|
||||
public static bool GetIsVisible(PlayerContext playerContext, bool desiredSelfVisibility, bool desiredFriendsVisibility, bool desiredPartyVisibility, bool desiredAllianceVisibility, bool desiredEnemiesVisibility, bool desiredOthersVisibility)
|
||||
{
|
||||
if (playerContext.HasFlag(PlayerContext.Self))
|
||||
{
|
||||
return desiredSelfVisibility;
|
||||
}
|
||||
|
||||
bool isVisible = false;
|
||||
var isVisible = false;
|
||||
|
||||
if (playerContext.HasFlag(PlayerContext.Friend))
|
||||
{
|
||||
isVisible |= desiredFriendsVisibility;
|
||||
}
|
||||
|
||||
if (playerContext.HasFlag(PlayerContext.Party))
|
||||
{
|
||||
isVisible |= desiredPartyVisibility;
|
||||
}
|
||||
|
||||
if (!playerContext.HasFlag(PlayerContext.Party) && playerContext.HasFlag(PlayerContext.Alliance))
|
||||
{
|
||||
isVisible |= desiredAllianceVisibility;
|
||||
}
|
||||
|
||||
if (playerContext.HasFlag(PlayerContext.Enemy))
|
||||
{
|
||||
isVisible |= desiredEnemiesVisibility;
|
||||
}
|
||||
|
||||
if (playerContext == PlayerContext.None)
|
||||
{
|
||||
isVisible |= desiredOthersVisibility;
|
||||
}
|
||||
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
public static bool GetIsVisible(PlayerCharacter playerCharacter, bool desiredSelfVisibility, bool desiredFriendsVisibility, bool desiredPartyVisibility, bool desiredAllianceVisibility, bool desiredEnemiesVisibility, bool desiredOthersVisibility)
|
||||
public static bool GetIsVisible(IPlayerCharacter playerCharacter, bool desiredSelfVisibility, bool desiredFriendsVisibility, bool desiredPartyVisibility, bool desiredAllianceVisibility, bool desiredEnemiesVisibility, bool desiredOthersVisibility)
|
||||
{
|
||||
return GetIsVisible(GetPlayerContext(playerCharacter), desiredSelfVisibility, desiredFriendsVisibility, desiredPartyVisibility, desiredAllianceVisibility, desiredEnemiesVisibility, desiredOthersVisibility);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Party;
|
||||
using Dalamud.Game.Gui.ContextMenu;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using PlayerTags.Configuration;
|
||||
using PlayerTags.PluginStrings;
|
||||
using System;
|
||||
@@ -274,23 +277,23 @@ public class PluginData
|
||||
};
|
||||
}
|
||||
|
||||
public Identity? GetIdentity(GameObjectContextMenuOpenArgs contextMenuOpenedArgs)
|
||||
public Identity? GetIdentity(MenuTargetDefault taget)
|
||||
{
|
||||
if (string.IsNullOrEmpty(contextMenuOpenedArgs.Text?.TextValue)
|
||||
|| contextMenuOpenedArgs.ObjectWorld == 0
|
||||
|| contextMenuOpenedArgs.ObjectWorld == 65535)
|
||||
if (string.IsNullOrEmpty(taget.TargetName)
|
||||
|| taget.TargetHomeWorld.Id == 0
|
||||
|| taget.TargetHomeWorld.Id == 65535)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return GetIdentity(contextMenuOpenedArgs.Text?.TextValue ?? string.Empty, contextMenuOpenedArgs.ObjectWorld);
|
||||
return GetIdentity(taget.TargetName, taget.TargetHomeWorld.Id);
|
||||
}
|
||||
|
||||
public Identity GetIdentity(PlayerCharacter playerCharacter)
|
||||
public Identity GetIdentity(IPlayerCharacter playerCharacter)
|
||||
{
|
||||
return GetIdentity(playerCharacter.Name.TextValue, playerCharacter.HomeWorld.Id);
|
||||
}
|
||||
|
||||
public Identity GetIdentity(PartyMember partyMember)
|
||||
public Identity GetIdentity(IPartyMember partyMember)
|
||||
{
|
||||
return GetIdentity(partyMember.Name.TextValue, partyMember.World.Id);
|
||||
}
|
||||
|
||||
@@ -149,13 +149,6 @@ public class Tag
|
||||
[InheritableCategory("TextCategory")]
|
||||
public InheritableValue<bool> IsTextColorAppliedToNameplateFreeCompany = new(false);
|
||||
|
||||
//[InheritableCategory("NameplateCategory")]
|
||||
//public InheritableValue<NameplateFreeCompanyVisibility> NameplateFreeCompanyVisibility = new InheritableValue<NameplateFreeCompanyVisibility>(Data.NameplateFreeCompanyVisibility.Default);
|
||||
//[InheritableCategory("NameplateCategory")]
|
||||
//public InheritableValue<NameplateTitleVisibility> NameplateTitleVisibility = new InheritableValue<NameplateTitleVisibility>(Data.NameplateTitleVisibility.Default);
|
||||
//[InheritableCategory("NameplateCategory")]
|
||||
//public InheritableValue<NameplateTitlePosition> NameplateTitlePosition = new InheritableValue<NameplateTitlePosition>(Data.NameplateTitlePosition.Default);
|
||||
|
||||
[InheritableCategory("PositionCategory")]
|
||||
public InheritableValue<TagPosition> TagPositionInChat = new(TagPosition.Before);
|
||||
[InheritableCategory("PositionCategory")]
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Pilz.Dalamud.Tools.Strings;
|
||||
using PlayerTags.Configuration;
|
||||
using PlayerTags.Data;
|
||||
using PlayerTags.Inheritables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -18,19 +21,19 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
/// <summary>
|
||||
/// A match found within a string.
|
||||
/// </summary>
|
||||
private class StringMatch
|
||||
private class StringMatch(SeString seString)
|
||||
{
|
||||
/// <summary>
|
||||
/// The string that the match was found in.
|
||||
/// </summary>
|
||||
public SeString SeString { get; init; }
|
||||
public SeString SeString { get; init; } = seString;
|
||||
|
||||
public List<Payload> DisplayTextPayloads { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The matching game object if one exists
|
||||
/// </summary>
|
||||
public GameObject? GameObject { get; init; }
|
||||
public IGameObject? GameObject { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// A matching player payload if one exists.
|
||||
@@ -57,15 +60,7 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
|
||||
public bool IsLocalPlayer
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetMatchTextInternal() == PluginServices.ClientState.LocalPlayer.Name.TextValue;
|
||||
}
|
||||
}
|
||||
|
||||
public StringMatch(SeString seString)
|
||||
{
|
||||
SeString = seString;
|
||||
get => GetMatchTextInternal() == PluginServices.ClientState.LocalPlayer.Name.TextValue;
|
||||
}
|
||||
|
||||
private string GetMatchTextInternal()
|
||||
@@ -96,16 +91,17 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
|
||||
public ChatTagTargetFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) : base(pluginConfiguration, pluginData)
|
||||
{
|
||||
PluginServices.ChatGui.ChatMessage += Chat_ChatMessage;
|
||||
PluginServices.ChatGui.ChatMessage += ChatGui_ChatMessage;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
PluginServices.ChatGui.ChatMessage -= Chat_ChatMessage;
|
||||
PluginServices.ChatGui.ChatMessage -= ChatGui_ChatMessage;
|
||||
base.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
|
||||
private void ChatGui_ChatMessage(XivChatType type, int timestamp, ref SeString sender, ref SeString message, ref bool isHandled)
|
||||
{
|
||||
if (EnableGlobal && pluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType].IsApplyTagsToAllChatMessagesEnabled)
|
||||
{
|
||||
@@ -117,10 +113,7 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
protected override bool IsIconVisible(Tag tag)
|
||||
{
|
||||
if (tag.IsRoleIconVisibleInChat.InheritedValue != null)
|
||||
{
|
||||
return tag.IsRoleIconVisibleInChat.InheritedValue.Value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -330,14 +323,14 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
=> tag.TagPositionInChat.InheritedValue != null && tag.TargetChatTypes.InheritedValue != null &&
|
||||
(tag.TargetChatTypes.InheritedValue.Contains(chatType) || (!Enum.IsDefined(chatType) && (tag.TargetChatTypesIncludeUndefined?.InheritedValue ?? false)));
|
||||
|
||||
if (stringMatch.GameObject is PlayerCharacter playerCharacter)
|
||||
if (stringMatch.GameObject is IPlayerCharacter playerCharacter)
|
||||
{
|
||||
// Add the job tag
|
||||
if (playerCharacter.ClassJob.GameData != null && pluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag))
|
||||
{
|
||||
if (isTagEnabled(jobTag))
|
||||
{
|
||||
var payloads = GetPayloads(jobTag, stringMatch.GameObject);
|
||||
var payloads = GetPayloads(jobTag, playerCharacter);
|
||||
if (payloads.Any())
|
||||
{
|
||||
var insertBehindNumberPrefix = jobTag.InsertBehindNumberPrefixInChat?.Value ?? true;
|
||||
@@ -395,7 +388,7 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
{
|
||||
Identity identity = pluginData.GetIdentity(stringMatch.PlayerPayload);
|
||||
|
||||
if (stringMatch.GameObject is PlayerCharacter playerCharacter1)
|
||||
if (stringMatch.GameObject is IPlayerCharacter playerCharacter1)
|
||||
{
|
||||
if (playerCharacter1.ClassJob.GameData != null && pluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag) && isTagEnabled(jobTag))
|
||||
applyTextFormatting(jobTag);
|
||||
@@ -425,4 +418,72 @@ public class ChatTagTargetFeature : TagTargetFeature
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTextFormatting(IGameObject? gameObject, Tag tag, SeString[] destStrings, InheritableValue<bool>[] textColorApplied, List<Payload> preferedPayloads, ushort? overwriteTextColor = null)
|
||||
{
|
||||
if (IsTagVisible(tag, gameObject))
|
||||
{
|
||||
for (int i = 0; i < destStrings.Length; i++)
|
||||
{
|
||||
var destString = destStrings[i];
|
||||
var isTextColorApplied = textColorApplied[i];
|
||||
applyTextColor(destString, isTextColorApplied, tag.TextColor);
|
||||
}
|
||||
}
|
||||
|
||||
void applyTextColor(SeString destPayload, InheritableValue<bool> enableFlag, InheritableValue<ushort> colorValue)
|
||||
{
|
||||
var colorToUse = overwriteTextColor ?? colorValue?.InheritedValue;
|
||||
if (shouldApplyFormattingPayloads(destPayload)
|
||||
&& enableFlag.InheritedValue != null
|
||||
&& enableFlag.InheritedValue.Value
|
||||
&& colorToUse != null)
|
||||
applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorToUse.Value), new UIForegroundPayload(0));
|
||||
}
|
||||
|
||||
bool shouldApplyFormattingPayloads(SeString destPayload)
|
||||
=> destPayload.Payloads.Any(payload => payload is TextPayload || payload is PlayerPayload);
|
||||
|
||||
void applyTextFormattingPayloads(SeString destPayload, Payload startPayload, Payload endPayload)
|
||||
{
|
||||
if (preferedPayloads == null || !preferedPayloads.Any())
|
||||
applyTextFormattingPayloadToStartAndEnd(destPayload, startPayload, endPayload);
|
||||
else
|
||||
applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayloads);
|
||||
}
|
||||
|
||||
void applyTextFormattingPayloadToStartAndEnd(SeString destPayload, Payload startPayload, Payload endPayload)
|
||||
{
|
||||
destPayload.Payloads.Insert(0, startPayload);
|
||||
destPayload.Payloads.Add(endPayload);
|
||||
}
|
||||
|
||||
void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, List<Payload> preferedPayload)
|
||||
{
|
||||
int payloadStartIndex = destPayload.Payloads.IndexOf(preferedPayloads.First());
|
||||
destPayload.Payloads.Insert(payloadStartIndex, startPayload);
|
||||
|
||||
int payloadEndIndex = destPayload.Payloads.IndexOf(preferedPayloads.Last());
|
||||
destPayload.Payloads.Insert(payloadEndIndex + 1, endPayload);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies changes to the given string.
|
||||
/// </summary>
|
||||
/// <param name="seString">The string to apply changes to.</param>
|
||||
/// <param name="stringChanges">The changes to apply.</param>
|
||||
/// <param name="anchorPayload">The payload in the string that changes should be anchored to. If there is no anchor, the changes will be applied to the entire string.</param>
|
||||
protected void ApplyStringChanges(SeString seString, StringChanges stringChanges, List<Payload> anchorPayloads = null, Payload anchorReplacePayload = null)
|
||||
{
|
||||
var props = new StringChangesProps
|
||||
{
|
||||
Destination = seString,
|
||||
AnchorPayload = anchorReplacePayload,
|
||||
AnchorPayloads = anchorPayloads,
|
||||
StringChanges = stringChanges
|
||||
};
|
||||
|
||||
StringUpdateFactory.ApplyStringChanges(props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Game.Gui.ContextMenu;
|
||||
using PlayerTags.Configuration;
|
||||
using PlayerTags.Data;
|
||||
using PlayerTags.Resources;
|
||||
@@ -29,33 +29,25 @@ public class CustomTagsContextMenuFeature : FeatureBase, IDisposable
|
||||
"SocialList",
|
||||
];
|
||||
|
||||
private DalamudContextMenu? m_ContextMenu;
|
||||
|
||||
public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, PluginData pluginData, IDalamudPluginInterface pluginInterface) : base(pluginConfiguration, pluginData)
|
||||
public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) : base(pluginConfiguration, pluginData)
|
||||
{
|
||||
m_ContextMenu = new DalamudContextMenu(pluginInterface);
|
||||
m_ContextMenu.OnOpenGameObjectContextMenu += ContextMenuHooks_ContextMenuOpened;
|
||||
PluginServices.ContextMenu.OnMenuOpened += ContextMenu_OnMenuOpened; ;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_ContextMenu != null)
|
||||
{
|
||||
m_ContextMenu.OnOpenGameObjectContextMenu -= ContextMenuHooks_ContextMenuOpened;
|
||||
((IDisposable)m_ContextMenu).Dispose();
|
||||
m_ContextMenu = null;
|
||||
}
|
||||
PluginServices.ContextMenu.OnMenuOpened -= ContextMenu_OnMenuOpened;
|
||||
}
|
||||
|
||||
private void ContextMenuHooks_ContextMenuOpened(GameObjectContextMenuOpenArgs contextMenuOpenedArgs)
|
||||
private void ContextMenu_OnMenuOpened(IMenuOpenedArgs args)
|
||||
{
|
||||
if (!EnableGlobal || !pluginConfiguration.IsCustomTagsContextMenuEnabled
|
||||
|| !supportedAddonNames.Contains(contextMenuOpenedArgs.ParentAddonName))
|
||||
{
|
||||
|| args.MenuType != ContextMenuType.Default
|
||||
|| args.Target is not MenuTargetDefault menuTarget
|
||||
|| !supportedAddonNames.Contains(args.AddonName))
|
||||
return;
|
||||
}
|
||||
|
||||
Identity? identity = pluginData.GetIdentity(contextMenuOpenedArgs);
|
||||
Identity? identity = pluginData.GetIdentity(menuTarget);
|
||||
if (identity != null)
|
||||
{
|
||||
var allTags = new Dictionary<Tag, bool>();
|
||||
@@ -75,18 +67,20 @@ public class CustomTagsContextMenuFeature : FeatureBase, IDisposable
|
||||
menuItemText = Strings.Loc_Static_ContextMenu_AddTag;
|
||||
menuItemText = string.Format(menuItemText, tag.Key.Text.Value);
|
||||
|
||||
contextMenuOpenedArgs.AddCustomItem(
|
||||
new GameObjectContextMenuItem(menuItemText, openedEventArgs =>
|
||||
args.AddMenuItem(new()
|
||||
{
|
||||
IsSubmenu = false,
|
||||
IsEnabled = true,
|
||||
Name = menuItemText,
|
||||
OnClicked = openedEventArgs =>
|
||||
{
|
||||
if (tag.Value)
|
||||
pluginData.RemoveCustomTagFromIdentity(tag.Key, identity);
|
||||
else
|
||||
pluginData.AddCustomTagToIdentity(tag.Key, identity);
|
||||
pluginConfiguration.Save(pluginData);
|
||||
})
|
||||
{
|
||||
IsSubMenu = false
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.Gui.NamePlate;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Pilz.Dalamud.Icons;
|
||||
using Pilz.Dalamud.Nameplates.Tools;
|
||||
using Pilz.Dalamud.Tools.NamePlates;
|
||||
using Pilz.Dalamud.Tools.Strings;
|
||||
using PlayerTags.Configuration;
|
||||
using PlayerTags.Data;
|
||||
using PlayerTags.GameInterface.Nameplates;
|
||||
using PlayerTags.Inheritables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -19,62 +21,19 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
{
|
||||
private readonly StatusIconPriorizer statusiconPriorizer;
|
||||
private readonly JobIconSets jobIconSets = new();
|
||||
private Nameplate? m_Nameplate;
|
||||
|
||||
public NameplateTagTargetFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) : base(pluginConfiguration, pluginData)
|
||||
{
|
||||
statusiconPriorizer = new(pluginConfiguration.StatusIconPriorizerSettings);
|
||||
|
||||
PluginServices.ClientState.Login += ClientState_Login;
|
||||
PluginServices.ClientState.Logout += ClientState_Logout;
|
||||
|
||||
Hook();
|
||||
PluginServices.NamePlateGui.OnNamePlateUpdate += NamePlateGui_OnNamePlateUpdate;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Unhook();
|
||||
|
||||
PluginServices.ClientState.Logout -= ClientState_Logout;
|
||||
PluginServices.ClientState.Login -= ClientState_Login;
|
||||
|
||||
PluginServices.NamePlateGui.OnNamePlateUpdate -= NamePlateGui_OnNamePlateUpdate;
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
private void Hook()
|
||||
{
|
||||
if (m_Nameplate == null)
|
||||
{
|
||||
m_Nameplate = new();
|
||||
|
||||
if (!m_Nameplate.IsValid)
|
||||
m_Nameplate = null;
|
||||
|
||||
if (m_Nameplate != null)
|
||||
m_Nameplate.PlayerNameplateUpdated += Nameplate_PlayerNameplateUpdated;
|
||||
}
|
||||
}
|
||||
|
||||
private void Unhook()
|
||||
{
|
||||
if (m_Nameplate != null)
|
||||
{
|
||||
m_Nameplate.PlayerNameplateUpdated -= Nameplate_PlayerNameplateUpdated;
|
||||
m_Nameplate.Dispose();
|
||||
m_Nameplate = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClientState_Login()
|
||||
{
|
||||
Hook();
|
||||
}
|
||||
|
||||
private void ClientState_Logout()
|
||||
{
|
||||
Unhook();
|
||||
}
|
||||
|
||||
protected override bool IsIconVisible(Tag tag)
|
||||
{
|
||||
if (tag.IsRoleIconVisibleInNameplates.InheritedValue != null)
|
||||
@@ -89,35 +48,33 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args)
|
||||
private void NamePlateGui_OnNamePlateUpdate(INamePlateUpdateContext context, IReadOnlyList<INamePlateUpdateHandler> handlers)
|
||||
{
|
||||
if (!EnableGlobal) return;
|
||||
if (!EnableGlobal)
|
||||
return;
|
||||
|
||||
var beforeTitleBytes = args.Title.Encode();
|
||||
var iconID = args.IconId;
|
||||
var generalOptions = pluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType];
|
||||
|
||||
AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID, generalOptions);
|
||||
|
||||
args.IconId = iconID;
|
||||
|
||||
if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName)
|
||||
args.IsTitleAboveName = true;
|
||||
else if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName)
|
||||
args.IsTitleAboveName = false;
|
||||
|
||||
if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.Always)
|
||||
args.IsTitleVisible = true;
|
||||
else if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.Never)
|
||||
args.IsTitleVisible = false;
|
||||
else if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags)
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(args.Title.Encode());
|
||||
args.IsTitleVisible = hasTitleChanged;
|
||||
}
|
||||
var beforeTitleBytes = handler.InfoView.Title.Encode();
|
||||
var generalOptions = pluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType];
|
||||
|
||||
if (generalOptions.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never)
|
||||
args.FreeCompany.Payloads.Clear();
|
||||
AddTagsToNameplate(handler, generalOptions);
|
||||
|
||||
if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName)
|
||||
handler.IsPrefixTitle = true;
|
||||
else if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName)
|
||||
handler.IsPrefixTitle = false;
|
||||
|
||||
if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.Always)
|
||||
handler.DisplayTitle = true;
|
||||
else if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.Never)
|
||||
handler.DisplayTitle = false;
|
||||
else if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags)
|
||||
handler.DisplayTitle = !beforeTitleBytes.SequenceEqual(handler.InfoView.Title.Encode());
|
||||
|
||||
if (generalOptions.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never)
|
||||
handler.RemoveFreeCompanyTag();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -131,38 +88,27 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
{
|
||||
if (payloadChanges.Any())
|
||||
{
|
||||
var changes = nameplateChanges.GetChanges((NameplateElements)nameplateElement);
|
||||
AddPayloadChanges((StringPosition)tagPosition, payloadChanges, changes, forceUsingSingleAnchorPayload);
|
||||
var changes = nameplateChanges.GetChange((NameplateElements)nameplateElement);
|
||||
AddPayloadChanges((StringPosition)tagPosition, payloadChanges, changes.Changes, forceUsingSingleAnchorPayload);
|
||||
}
|
||||
}
|
||||
|
||||
private NameplateChanges GenerateEmptyNameplateChanges(SeString name, SeString title, SeString freeCompany)
|
||||
{
|
||||
NameplateChanges nameplateChanges = new();
|
||||
|
||||
nameplateChanges.GetProps(NameplateElements.Name).Destination = name;
|
||||
nameplateChanges.GetProps(NameplateElements.Title).Destination = title;
|
||||
nameplateChanges.GetProps(NameplateElements.FreeCompany).Destination = freeCompany;
|
||||
|
||||
return nameplateChanges;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds tags to the nameplate of a game object.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The game object context.</param>
|
||||
/// <param name="playerCharacter">The game object context.</param>
|
||||
/// <param name="name">The name text to change.</param>
|
||||
/// <param name="title">The title text to change.</param>
|
||||
/// <param name="freeCompany">The free company text to change.</param>
|
||||
private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon, GeneralOptionsClass generalOptions)
|
||||
private void AddTagsToNameplate(INamePlateUpdateHandler handler, GeneralOptionsClass generalOptions)
|
||||
{
|
||||
var playerCharacter = gameObject as PlayerCharacter;
|
||||
int? newStatusIcon = null;
|
||||
NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany);
|
||||
var nameplateChanges = new NameplateChanges(handler);
|
||||
|
||||
if (playerCharacter != null && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore))
|
||||
if (handler.PlayerCharacter != null && (!handler.PlayerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore))
|
||||
{
|
||||
var classJob = playerCharacter.ClassJob;
|
||||
var classJob = handler.PlayerCharacter.ClassJob;
|
||||
var classJobGameData = classJob?.GameData;
|
||||
|
||||
// Add the job tags
|
||||
@@ -175,7 +121,7 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
// Add the randomly generated name tag payload
|
||||
if (pluginConfiguration.IsPlayerNameRandomlyGenerated)
|
||||
{
|
||||
var characterName = playerCharacter.Name.TextValue;
|
||||
var characterName = handler.PlayerCharacter.Name.TextValue;
|
||||
if (characterName != null)
|
||||
{
|
||||
var generatedName = RandomNameGenerator.Generate(characterName);
|
||||
@@ -185,7 +131,7 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
}
|
||||
|
||||
// Add custom tags
|
||||
Identity identity = pluginData.GetIdentity(playerCharacter);
|
||||
Identity identity = pluginData.GetIdentity(handler.PlayerCharacter);
|
||||
foreach (var customTagId in identity.CustomTagIds)
|
||||
{
|
||||
var customTag = pluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId);
|
||||
@@ -197,11 +143,11 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
{
|
||||
if (tag.TagTargetInNameplates.InheritedValue != null && tag.TagPositionInNameplates.InheritedValue != null)
|
||||
{
|
||||
var payloads = GetPayloads(tag, gameObject);
|
||||
if (payloads.Any())
|
||||
var payloads = GetPayloads(tag, handler.PlayerCharacter);
|
||||
if (payloads.Length != 0)
|
||||
AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges, false);
|
||||
}
|
||||
if (IsTagVisible(tag, gameObject) && newStatusIcon == null && classJob != null && (tag.IsJobIconVisibleInNameplates?.InheritedValue ?? false))
|
||||
if (IsTagVisible(tag, handler.PlayerCharacter) && newStatusIcon == null && classJob != null && (tag.IsJobIconVisibleInNameplates?.InheritedValue ?? false))
|
||||
newStatusIcon = jobIconSets.GetJobIcon(tag.JobIconSet?.InheritedValue ?? JobIconSetName.Framed, classJob.Id);
|
||||
}
|
||||
}
|
||||
@@ -209,21 +155,23 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
// Apply new status icon
|
||||
if (newStatusIcon != null)
|
||||
{
|
||||
var change = nameplateChanges.GetChange(NameplateElements.Name, StringPosition.Before);
|
||||
NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer, pluginConfiguration.MoveStatusIconToNameplateTextIfPossible);
|
||||
NameplateUpdateFactory.ApplyStatusIconWithPrio(handler, (int)newStatusIcon, ActivityContextManager.CurrentActivityContext, statusiconPriorizer, pluginConfiguration.MoveStatusIconToNameplateTextIfPossible);
|
||||
}
|
||||
|
||||
// Gray out the nameplate
|
||||
if (playerCharacter != null && playerCharacter.IsDead && generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.GrayOut)
|
||||
GrayOutNameplate(gameObject, nameplateChanges);
|
||||
|
||||
// Build the final strings out of the payloads
|
||||
ApplyNameplateChanges(nameplateChanges);
|
||||
|
||||
if (playerCharacter != null && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.Include))
|
||||
NameplateUpdateFactory.ApplyNameplateChanges(new NameplateChangesProps
|
||||
{
|
||||
// An additional step to apply text color to additional locations
|
||||
Identity identity = pluginData.GetIdentity(playerCharacter);
|
||||
Changes = nameplateChanges
|
||||
});
|
||||
|
||||
// Gray out the nameplate
|
||||
if (handler.PlayerCharacter != null && handler.PlayerCharacter.IsDead && generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.GrayOut)
|
||||
GrayOutNameplate(handler.PlayerCharacter, nameplateChanges);
|
||||
|
||||
// Apply text color
|
||||
if (handler.PlayerCharacter != null && (!handler.PlayerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.Include))
|
||||
{
|
||||
Identity identity = pluginData.GetIdentity(handler.PlayerCharacter);
|
||||
foreach (var customTagId in identity.CustomTagIds)
|
||||
{
|
||||
var customTag = pluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId);
|
||||
@@ -231,36 +179,40 @@ public class NameplateTagTargetFeature : TagTargetFeature
|
||||
applyTextFormatting(customTag);
|
||||
}
|
||||
|
||||
if (playerCharacter.ClassJob.GameData != null && pluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag))
|
||||
if (handler.PlayerCharacter.ClassJob.GameData != null && pluginData.JobTags.TryGetValue(handler.PlayerCharacter.ClassJob.GameData.Abbreviation, out var jobTag))
|
||||
applyTextFormatting(jobTag);
|
||||
|
||||
void applyTextFormatting(Tag tag)
|
||||
{
|
||||
var destStrings = new[] { name, title, freeCompany };
|
||||
var isTextColorApplied = new[] { tag.IsTextColorAppliedToNameplateName, tag.IsTextColorAppliedToNameplateTitle, tag.IsTextColorAppliedToNameplateFreeCompany };
|
||||
ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null);
|
||||
var dic = new Dictionary<NameplateElementChange, InheritableValue<bool>>
|
||||
{
|
||||
{ nameplateChanges.GetChange(NameplateElements.Name), tag.IsTextColorAppliedToNameplateName },
|
||||
{ nameplateChanges.GetChange(NameplateElements.Title), tag.IsTextColorAppliedToNameplateTitle },
|
||||
{ nameplateChanges.GetChange(NameplateElements.FreeCompany), tag.IsTextColorAppliedToNameplateFreeCompany },
|
||||
};
|
||||
ApplyTextFormatting(handler.PlayerCharacter, tag, dic, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GrayOutNameplate(GameObject gameObject, NameplateChanges nameplateChanges)
|
||||
private void GrayOutNameplate(IPlayerCharacter playerCharacter, NameplateChanges nameplateChanges)
|
||||
{
|
||||
if (gameObject is PlayerCharacter playerCharacter)
|
||||
foreach (var element in Enum.GetValues<NameplateElements>())
|
||||
nameplateChanges.GetChange(element).ApplyFormatting(new SeString().Append(new UIForegroundPayload(3)), new SeString().Append(new UIForegroundPayload(0)));
|
||||
}
|
||||
|
||||
protected void ApplyTextFormatting(IPlayerCharacter? gameObject, Tag tag, IEnumerable<KeyValuePair<NameplateElementChange, InheritableValue<bool>>> changes, ushort? overwriteTextColor = null)
|
||||
{
|
||||
if (IsTagVisible(tag, gameObject))
|
||||
{
|
||||
foreach (NameplateElements element in Enum.GetValues<NameplateElements>())
|
||||
foreach (var kvp in changes)
|
||||
{
|
||||
nameplateChanges.GetChange(element, StringPosition.Before).Payloads.Add(new UIForegroundPayload(3));
|
||||
nameplateChanges.GetChange(element, StringPosition.After).Payloads.Add(new UIForegroundPayload(0));
|
||||
var change = kvp.Key;
|
||||
var enableFlag = kvp.Value;
|
||||
|
||||
if (enableFlag.InheritedValue != null && enableFlag.InheritedValue.Value && (overwriteTextColor ?? tag.TextColor?.InheritedValue) is ushort colorToUse)
|
||||
change.ApplyFormatting(new SeString().Append(new UIForegroundPayload(colorToUse)), new SeString().Append(new UIForegroundPayload(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ApplyNameplateChanges(NameplateChanges nameplateChanges)
|
||||
{
|
||||
var props = new NameplateChangesProps
|
||||
{
|
||||
Changes = nameplateChanges
|
||||
};
|
||||
NameplateUpdateFactory.ApplyNameplateChanges(props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,36 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Pilz.Dalamud.ActivityContexts;
|
||||
using Pilz.Dalamud.Tools.Strings;
|
||||
using PlayerTags.Configuration;
|
||||
using PlayerTags.Configuration.GameConfig;
|
||||
using PlayerTags.Data;
|
||||
using PlayerTags.Inheritables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using GameObject = Dalamud.Game.ClientState.Objects.Types.GameObject;
|
||||
|
||||
namespace PlayerTags.Features;
|
||||
|
||||
/// <summary>
|
||||
/// The base of a feature that adds tags to UI elements.
|
||||
/// </summary>
|
||||
public abstract class TagTargetFeature : FeatureBase, IDisposable
|
||||
public abstract class TagTargetFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) : FeatureBase(pluginConfiguration, pluginData), IDisposable
|
||||
{
|
||||
public ActivityContextManager ActivityContextManager { get; init; }
|
||||
|
||||
protected TagTargetFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) : base(pluginConfiguration, pluginData)
|
||||
{
|
||||
ActivityContextManager = new();
|
||||
}
|
||||
public ActivityContextManager ActivityContextManager { get; init; } = new();
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
ActivityContextManager.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected abstract bool IsIconVisible(Tag tag);
|
||||
|
||||
protected abstract bool IsTextVisible(Tag tag);
|
||||
|
||||
protected bool IsTagVisible(Tag tag, GameObject? gameObject)
|
||||
protected bool IsTagVisible(Tag tag, IGameObject? gameObject)
|
||||
{
|
||||
bool isVisibleForActivity = ActivityContextHelper.GetIsVisible(ActivityContextManager.CurrentActivityContext.ActivityType,
|
||||
tag.IsVisibleInPveDuties.InheritedValue ?? false,
|
||||
@@ -42,11 +38,9 @@ public abstract class TagTargetFeature : FeatureBase, IDisposable
|
||||
tag.IsVisibleInOverworld.InheritedValue ?? false);
|
||||
|
||||
if (!isVisibleForActivity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gameObject is PlayerCharacter playerCharacter)
|
||||
if (gameObject is IPlayerCharacter playerCharacter)
|
||||
{
|
||||
bool isVisibleForPlayer = PlayerContextHelper.GetIsVisible(playerCharacter,
|
||||
tag.IsVisibleForSelf.InheritedValue ?? false,
|
||||
@@ -57,9 +51,7 @@ public abstract class TagTargetFeature : FeatureBase, IDisposable
|
||||
tag.IsVisibleForOtherPlayers.InheritedValue ?? false);
|
||||
|
||||
if (!isVisibleForPlayer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -71,13 +63,10 @@ public abstract class TagTargetFeature : FeatureBase, IDisposable
|
||||
/// <param name="gameObject">The game object to get payloads for.</param>
|
||||
/// <param name="tag">The tag config to get payloads for.</param>
|
||||
/// <returns>A list of payloads for the given tag.</returns>
|
||||
protected Payload[] GetPayloads(Tag tag, GameObject? gameObject)
|
||||
protected Payload[] GetPayloads(Tag tag, IGameObject? playerCharacter)
|
||||
{
|
||||
if (!IsTagVisible(tag, gameObject))
|
||||
{
|
||||
return Array.Empty<Payload>();
|
||||
}
|
||||
|
||||
if (!IsTagVisible(tag, playerCharacter))
|
||||
return [];
|
||||
return CreatePayloads(tag);
|
||||
}
|
||||
|
||||
@@ -89,60 +78,42 @@ public abstract class TagTargetFeature : FeatureBase, IDisposable
|
||||
private Payload[] CreatePayloads(Tag tag)
|
||||
{
|
||||
List<Payload> newPayloads = [];
|
||||
|
||||
BitmapFontIcon? icon = null;
|
||||
string? text = null;
|
||||
|
||||
if (IsIconVisible(tag))
|
||||
{
|
||||
icon = tag.Icon.InheritedValue;
|
||||
}
|
||||
|
||||
if (icon != null && icon.Value != BitmapFontIcon.None)
|
||||
{
|
||||
newPayloads.Add(new IconPayload(icon.Value));
|
||||
}
|
||||
|
||||
string? text = null;
|
||||
if (IsTextVisible(tag))
|
||||
{
|
||||
text = tag.Text.InheritedValue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
if (tag.IsTextItalic.InheritedValue != null && tag.IsTextItalic.InheritedValue.Value)
|
||||
{
|
||||
newPayloads.Add(new EmphasisItalicPayload(true));
|
||||
}
|
||||
|
||||
if (tag.TextGlowColor.InheritedValue != null)
|
||||
{
|
||||
newPayloads.Add(new UIGlowPayload(tag.TextGlowColor.InheritedValue.Value));
|
||||
}
|
||||
|
||||
if (tag.TextColor.InheritedValue != null)
|
||||
{
|
||||
newPayloads.Add(new UIForegroundPayload(tag.TextColor.InheritedValue.Value));
|
||||
}
|
||||
|
||||
newPayloads.Add(new TextPayload(text));
|
||||
|
||||
if (tag.TextColor.InheritedValue != null)
|
||||
{
|
||||
newPayloads.Add(new UIForegroundPayload(0));
|
||||
}
|
||||
|
||||
if (tag.TextGlowColor.InheritedValue != null)
|
||||
{
|
||||
newPayloads.Add(new UIGlowPayload(0));
|
||||
}
|
||||
|
||||
if (tag.IsTextItalic.InheritedValue != null && tag.IsTextItalic.InheritedValue.Value)
|
||||
{
|
||||
newPayloads.Add(new EmphasisItalicPayload(false));
|
||||
}
|
||||
}
|
||||
|
||||
return newPayloads.ToArray();
|
||||
return [.. newPayloads];
|
||||
}
|
||||
|
||||
protected static string BuildPlayername(string name)
|
||||
@@ -198,91 +169,4 @@ public abstract class TagTargetFeature : FeatureBase, IDisposable
|
||||
changes.ForceUsingSingleAnchorPayload = forceUsingSingleAnchorPayload;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies changes to the given string.
|
||||
/// </summary>
|
||||
/// <param name="seString">The string to apply changes to.</param>
|
||||
/// <param name="stringChanges">The changes to apply.</param>
|
||||
/// <param name="anchorPayload">The payload in the string that changes should be anchored to. If there is no anchor, the changes will be applied to the entire string.</param>
|
||||
protected void ApplyStringChanges(SeString seString, StringChanges stringChanges, List<Payload> anchorPayloads = null, Payload anchorReplacePayload = null)
|
||||
{
|
||||
var props = new StringChangesProps
|
||||
{
|
||||
Destination = seString,
|
||||
AnchorPayload = anchorReplacePayload,
|
||||
AnchorPayloads = anchorPayloads,
|
||||
StringChanges = stringChanges
|
||||
};
|
||||
|
||||
StringUpdateFactory.ApplyStringChanges(props);
|
||||
}
|
||||
|
||||
protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue<bool>[] textColorApplied, List<Payload> preferedPayloads, ushort? overwriteTextColor = null)
|
||||
{
|
||||
if (IsTagVisible(tag, gameObject))
|
||||
{
|
||||
for (int i = 0; i < destStrings.Length; i++)
|
||||
{
|
||||
var destString = destStrings[i];
|
||||
var isTextColorApplied = textColorApplied[i];
|
||||
applyTextColor(destString, isTextColorApplied, tag.TextColor);
|
||||
//applyTextGlowColor(destString, isTextColorApplied, tag.TextGlowColor);
|
||||
//applyTextItalicColor(destString, tag.IsTextItalic); // Disabled, because that is needed only for a few parts somewhere else.
|
||||
}
|
||||
}
|
||||
|
||||
void applyTextColor(SeString destPayload, InheritableValue<bool> enableFlag, InheritableValue<ushort> colorValue)
|
||||
{
|
||||
var colorToUse = overwriteTextColor ?? colorValue?.InheritedValue;
|
||||
if (shouldApplyFormattingPayloads(destPayload)
|
||||
&& enableFlag.InheritedValue != null
|
||||
&& enableFlag.InheritedValue.Value
|
||||
&& colorToUse != null)
|
||||
applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorToUse.Value), new UIForegroundPayload(0));
|
||||
}
|
||||
|
||||
//void applyTextGlowColor(SeString destPayload, InheritableValue<bool> enableFlag, InheritableValue<ushort> colorValue)
|
||||
//{
|
||||
// if (shouldApplyFormattingPayloads(destPayload)
|
||||
// && enableFlag.InheritedValue != null
|
||||
// && enableFlag.InheritedValue.Value
|
||||
// && colorValue.InheritedValue != null)
|
||||
// applyTextFormattingPayloads(destPayload, new UIGlowPayload(colorValue.InheritedValue.Value), new UIGlowPayload(0));
|
||||
//}
|
||||
|
||||
//void applyTextItalicColor(SeString destPayload, InheritableValue<bool> italicValue)
|
||||
//{
|
||||
// if (shouldApplyFormattingPayloads(destPayload)
|
||||
// && italicValue.InheritedValue != null
|
||||
// && italicValue.InheritedValue.Value)
|
||||
// applyTextFormattingPayloads(destPayload, new EmphasisItalicPayload(true), new EmphasisItalicPayload(false));
|
||||
//}
|
||||
|
||||
bool shouldApplyFormattingPayloads(SeString destPayload)
|
||||
=> destPayload.Payloads.Any(payload => payload is TextPayload || payload is PlayerPayload);
|
||||
|
||||
void applyTextFormattingPayloads(SeString destPayload, Payload startPayload, Payload endPayload)
|
||||
{
|
||||
if (preferedPayloads == null || !preferedPayloads.Any())
|
||||
applyTextFormattingPayloadToStartAndEnd(destPayload, startPayload, endPayload);
|
||||
else
|
||||
applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayloads);
|
||||
}
|
||||
|
||||
void applyTextFormattingPayloadToStartAndEnd(SeString destPayload, Payload startPayload, Payload endPayload)
|
||||
{
|
||||
destPayload.Payloads.Insert(0, startPayload);
|
||||
destPayload.Payloads.Add(endPayload);
|
||||
}
|
||||
|
||||
void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, List<Payload> preferedPayload)
|
||||
{
|
||||
int payloadStartIndex = destPayload.Payloads.IndexOf(preferedPayloads.First());
|
||||
destPayload.Payloads.Insert(payloadStartIndex, startPayload);
|
||||
|
||||
int payloadEndIndex = destPayload.Payloads.IndexOf(preferedPayloads.Last());
|
||||
destPayload.Payloads.Insert(payloadEndIndex + 1, endPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Memory;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace PlayerTags.GameInterface;
|
||||
|
||||
public static class GameInterfaceHelper
|
||||
{
|
||||
public static SeString ReadSeString(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return new SeString();
|
||||
}
|
||||
|
||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||
{
|
||||
return SeString.Parse(bytes);
|
||||
}
|
||||
|
||||
return new SeString();
|
||||
}
|
||||
|
||||
public static bool TryReadSeString(IntPtr ptr, out SeString? seString)
|
||||
{
|
||||
seString = null;
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||
{
|
||||
seString = SeString.Parse(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string? ReadString(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||
{
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool TryReadString(IntPtr ptr, out string? str)
|
||||
{
|
||||
str = null;
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryReadStringBytes(ptr, out var bytes) && bytes != null)
|
||||
{
|
||||
str = Encoding.UTF8.GetString(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryReadStringBytes(IntPtr ptr, out byte[]? bytes)
|
||||
{
|
||||
bytes = null;
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var size = 0;
|
||||
while (Marshal.ReadByte(ptr, size) != 0)
|
||||
{
|
||||
size++;
|
||||
}
|
||||
|
||||
bytes = new byte[size];
|
||||
Marshal.Copy(ptr, bytes, 0, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IntPtr PluginAllocate(byte[] bytes)
|
||||
{
|
||||
IntPtr pointer = Marshal.AllocHGlobal(bytes.Length + 1);
|
||||
Marshal.Copy(bytes, 0, pointer, bytes.Length);
|
||||
Marshal.WriteByte(pointer, bytes.Length, 0);
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
public static IntPtr PluginAllocate(SeString seString)
|
||||
{
|
||||
return PluginAllocate(seString.Encode());
|
||||
}
|
||||
|
||||
public static void PluginFree(ref IntPtr ptr)
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static byte[] NullTerminate(this byte[] bytes)
|
||||
{
|
||||
if (bytes.Length == 0 || bytes[bytes.Length - 1] != 0)
|
||||
{
|
||||
var newBytes = new byte[bytes.Length + 1];
|
||||
Array.Copy(bytes, newBytes, bytes.Length);
|
||||
newBytes[^1] = 0;
|
||||
|
||||
return newBytes;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static unsafe IntPtr GameUIAllocate(ulong size)
|
||||
{
|
||||
return (IntPtr)IMemorySpace.GetUISpace()->Malloc(size, 0);
|
||||
}
|
||||
|
||||
public static unsafe void GameFree(ref IntPtr ptr, ulong size)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IMemorySpace.Free((void*)ptr, size);
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using Pilz.Dalamud.Nameplates;
|
||||
using System;
|
||||
|
||||
namespace PlayerTags.GameInterface.Nameplates;
|
||||
|
||||
/// <summary>
|
||||
/// Provides an interface to modify nameplates.
|
||||
/// </summary>
|
||||
public class Nameplate : IDisposable
|
||||
{
|
||||
public NameplateManager NameplateManager { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a player nameplate is updated by the game.
|
||||
/// </summary>
|
||||
public event PlayerNameplateUpdatedDelegate? PlayerNameplateUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the required hooks are in place and this instance is valid.
|
||||
/// </summary>
|
||||
public bool IsValid
|
||||
{
|
||||
get => NameplateManager != null && NameplateManager.IsValid;
|
||||
}
|
||||
|
||||
public Nameplate()
|
||||
{
|
||||
NameplateManager = new();
|
||||
NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged += Hooks_AddonNamePlate_SetPlayerNameManaged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged -= Hooks_AddonNamePlate_SetPlayerNameManaged;
|
||||
NameplateManager.Dispose();
|
||||
}
|
||||
|
||||
private void Hooks_AddonNamePlate_SetPlayerNameManaged(Pilz.Dalamud.Nameplates.EventArgs.AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlayerCharacter? playerCharacter = NameplateManager.GetNameplateGameObject<PlayerCharacter>(eventArgs.SafeNameplateObject);
|
||||
|
||||
if (playerCharacter != null)
|
||||
{
|
||||
var playerNameplateUpdatedArgs = new PlayerNameplateUpdatedArgs(playerCharacter, eventArgs);
|
||||
PlayerNameplateUpdated?.Invoke(playerNameplateUpdatedArgs);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginServices.PluginLog.Error(ex, $"SetPlayerNameplateDetour");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
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 => eventArgs.Name;
|
||||
}
|
||||
|
||||
public SeString Title
|
||||
{
|
||||
get => eventArgs.Title;
|
||||
}
|
||||
|
||||
public SeString FreeCompany
|
||||
{
|
||||
get => eventArgs.FreeCompany;
|
||||
}
|
||||
|
||||
public bool IsTitleVisible
|
||||
{
|
||||
get => eventArgs.IsTitleVisible;
|
||||
set => eventArgs.IsTitleVisible = value;
|
||||
}
|
||||
|
||||
public bool IsTitleAboveName
|
||||
{
|
||||
get => eventArgs.IsTitleAboveName;
|
||||
set => eventArgs.IsTitleAboveName = value;
|
||||
}
|
||||
|
||||
public int IconId
|
||||
{
|
||||
get => eventArgs.IconID;
|
||||
set => eventArgs.IconID = value;
|
||||
}
|
||||
|
||||
public PlayerNameplateUpdatedArgs(PlayerCharacter playerCharacter, AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs)
|
||||
{
|
||||
PlayerCharacter = playerCharacter;
|
||||
this.eventArgs = eventArgs;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
namespace PlayerTags.GameInterface.Nameplates;
|
||||
|
||||
public delegate void PlayerNameplateUpdatedDelegate(PlayerNameplateUpdatedArgs args);
|
||||
@@ -27,7 +27,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
PluginServices.Initialize(pluginInterface);
|
||||
Pilz.Dalamud.PluginServices.Initialize(pluginInterface);
|
||||
|
||||
pluginConfiguration = PluginConfiguration.LoadPluginConfig() ?? new PluginConfiguration();
|
||||
pluginConfiguration = PluginConfiguration.LoadPluginConfig() ?? new();
|
||||
pluginData = new PluginData(pluginConfiguration);
|
||||
pluginConfigurationUI = new PluginConfigurationUI(pluginConfiguration, pluginData);
|
||||
|
||||
@@ -40,7 +40,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
{
|
||||
HelpMessage = Resources.Strings.Loc_Command_playertags_v2
|
||||
});
|
||||
customTagsContextMenuFeature = new CustomTagsContextMenuFeature(pluginConfiguration, pluginData, pluginInterface);
|
||||
customTagsContextMenuFeature = new CustomTagsContextMenuFeature(pluginConfiguration, pluginData);
|
||||
nameplatesTagTargetFeature = new NameplateTagTargetFeature(pluginConfiguration, pluginData);
|
||||
chatTagTargetFeature = new ChatTagTargetFeature(pluginConfiguration, pluginData);
|
||||
}
|
||||
|
||||
@@ -6,18 +6,20 @@ namespace PlayerTags;
|
||||
|
||||
public class PluginServices
|
||||
{
|
||||
[PluginService] public static IDalamudPluginInterface DalamudPluginInterface { get; set; } = null!;
|
||||
[PluginService] public static IPluginLog PluginLog { get; set; } = null;
|
||||
[PluginService] public static IGameConfig GameConfig { get; set; } = null;
|
||||
[PluginService] public static IChatGui ChatGui { get; set; } = null!;
|
||||
[PluginService] public static IClientState ClientState { get; set; } = null!;
|
||||
[PluginService] public static ICommandManager CommandManager { get; set; } = null!;
|
||||
[PluginService] public static IDataManager DataManager { get; set; } = null!;
|
||||
[PluginService] public static IFramework Framework { get; set; } = null!;
|
||||
[PluginService] public static IGameGui GameGui { get; set; } = null!;
|
||||
[PluginService] public static IObjectTable ObjectTable { get; set; } = null!;
|
||||
[PluginService] public static IPartyList PartyList { get; set; } = null!;
|
||||
[PluginService] public static IGameInteropProvider GameInteropProvider { get; set; } = null;
|
||||
[PluginService] public static IDalamudPluginInterface DalamudPluginInterface { get; set; }
|
||||
[PluginService] public static IPluginLog PluginLog { get; set; }
|
||||
[PluginService] public static IGameConfig GameConfig { get; set; }
|
||||
[PluginService] public static IChatGui ChatGui { get; set; }
|
||||
[PluginService] public static IClientState ClientState { get; set; }
|
||||
[PluginService] public static ICommandManager CommandManager { get; set; }
|
||||
[PluginService] public static IDataManager DataManager { get; set; }
|
||||
[PluginService] public static IFramework Framework { get; set; }
|
||||
[PluginService] public static IGameGui GameGui { get; set; }
|
||||
[PluginService] public static IObjectTable ObjectTable { get; set; }
|
||||
[PluginService] public static IPartyList PartyList { get; set; }
|
||||
[PluginService] public static IGameInteropProvider GameInteropProvider { get; set; }
|
||||
[PluginService] public static IContextMenu ContextMenu { get; set; }
|
||||
[PluginService] public static INamePlateGui NamePlateGui { get; set; }
|
||||
|
||||
public static void Initialize(IDalamudPluginInterface pluginInterface)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user