migrate chat, nameplate, etc. to new api

This commit is contained in:
2024-07-10 13:39:55 +02:00
committed by Pascal
parent 8f644ce913
commit 4fb5cc0b9d
17 changed files with 232 additions and 615 deletions

View File

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

View File

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

View File

@@ -4,5 +4,5 @@ public enum NameplateElement
{
Name,
Title,
FreeCompany
FreeCompany,
}

View File

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

View File

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

View File

@@ -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")]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,3 +0,0 @@
namespace PlayerTags.GameInterface.Nameplates;
public delegate void PlayerNameplateUpdatedDelegate(PlayerNameplateUpdatedArgs args);

View File

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

View File

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