improve position and coloring of party number prefix

This commit is contained in:
2022-09-16 15:57:57 +02:00
parent 072702fc21
commit d04418fb2b
3 changed files with 103 additions and 56 deletions

View File

@@ -28,10 +28,7 @@ namespace PlayerTags.Features
/// </summary>
public SeString SeString { get; init; }
/// <summary>
/// The matching text payload.
/// </summary>
public TextPayload? TextPayload { get; init; }
public List<Payload> DisplayTextPayloads { get; init; } = new();
/// <summary>
/// The matching game object if one exists
@@ -43,16 +40,18 @@ namespace PlayerTags.Features
/// </summary>
public PlayerPayload? PlayerPayload { get; init; }
public Payload? PreferredPayload
public Payload? PlayerNamePayload
{
get
{
if (TextPayload != null)
{
return TextPayload;
}
Payload textPayload = null;
string textMatch = GetMatchText();
return PlayerPayload;
textPayload = DisplayTextPayloads.FirstOrDefault(n => n is TextPayload textPayload && textPayload.Text.Contains(textMatch));
textPayload ??= PlayerPayload;
textPayload ??= DisplayTextPayloads.FirstOrDefault();
return textPayload;
}
}
@@ -72,11 +71,6 @@ namespace PlayerTags.Features
return GameObject.Name.TextValue;
}
if (TextPayload != null)
{
return TextPayload.Text;
}
if (PlayerPayload != null)
{
return PlayerPayload.PlayerName;
@@ -107,8 +101,8 @@ namespace PlayerTags.Features
{
if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type))
{
AddTagsToChat(sender);
AddTagsToChat(message);
AddTagsToChat(sender, type, true);
AddTagsToChat(message, type, false);
}
}
@@ -139,31 +133,44 @@ namespace PlayerTags.Features
/// <returns>A list of matched game objects.</returns>
private List<StringMatch> GetStringMatches(SeString seString)
{
List<StringMatch> stringMatches = new List<StringMatch>();
List<StringMatch> stringMatches = new();
Stack<PlayerPayload> curPlayerPayload = new();
Stack<List<Payload>> curRefPayloads = new();
var defaultRawPayload = RawPayload.LinkTerminator.Data;
for (int payloadIndex = 0; payloadIndex < seString.Payloads.Count; ++payloadIndex)
foreach (var payload in seString.Payloads)
{
var payload = seString.Payloads[payloadIndex];
if (payload is PlayerPayload playerPayload)
{
curPlayerPayload.Push(playerPayload);
curRefPayloads.Push(new List<Payload>());
}
else if (payload is RawPayload rawPayload)
{
if (defaultRawPayload.SequenceEqual(rawPayload.Data))
finishCurrentMatch();
}
else
{
if (curRefPayloads.TryPeek(out List<Payload> result))
result.Add(payload);
}
}
// Finally finish, if not closed by RawPayload
finishCurrentMatch();
void finishCurrentMatch()
{
if (curPlayerPayload.TryPop(out PlayerPayload playerPayload))
{
var gameObject = PluginServices.ObjectTable.FirstOrDefault(gameObject => gameObject.Name.TextValue == playerPayload.PlayerName);
TextPayload? textPayload = null;
// The next payload MUST be a text payload
if (payloadIndex + 1 < seString.Payloads.Count)
{
textPayload = seString.Payloads[payloadIndex + 1] as TextPayload;
// Don't handle the text payload twice
payloadIndex++;
}
var stringMatch = new StringMatch(seString)
{
GameObject = gameObject,
PlayerPayload = playerPayload,
TextPayload = textPayload
DisplayTextPayloads = curRefPayloads.Pop()
};
stringMatches.Add(stringMatch);
}
@@ -172,12 +179,45 @@ namespace PlayerTags.Features
return stringMatches;
}
private void SplitOffPartyNumberPrefix(SeString sender, XivChatType type)
{
if (type == XivChatType.Party || type == XivChatType.Alliance)
{
PlayerPayload lastPlayerPayload = null;
foreach (var payload in sender.Payloads.ToArray())
{
if (payload is PlayerPayload playerPayload)
lastPlayerPayload = playerPayload;
else if (payload is TextPayload playerNamePayload && lastPlayerPayload != null)
{
// Get position of player name in payload
var indexOfPlayerName = playerNamePayload.Text.IndexOf(lastPlayerPayload.PlayerName);
if (indexOfPlayerName > 0)
{
// Split off the name from the prefix number
var prefixPayload = new TextPayload(playerNamePayload.Text[..indexOfPlayerName]);
playerNamePayload.Text = playerNamePayload.Text[indexOfPlayerName..];
// Add prefix number before the player name payload
var playerNamePayloadIndex = sender.Payloads.IndexOf(playerNamePayload);
sender.Payloads.Insert(playerNamePayloadIndex, prefixPayload);
}
}
}
}
}
/// <summary>
/// Adds all configured tags to a chat message.
/// </summary>
/// <param name="message">The message to change.</param>
private void AddTagsToChat(SeString message)
private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender)
{
// Split out the party/alliance number from the PlayerPayload
if (isSender)
SplitOffPartyNumberPrefix(message, chatType);
var stringMatches = GetStringMatches(message);
foreach (var stringMatch in stringMatches)
{
@@ -235,7 +275,7 @@ namespace PlayerTags.Features
}
// An additional step to apply text color to additional locations
if (stringMatch.PlayerPayload != null && stringMatch.PreferredPayload != null)
if (stringMatch.PlayerPayload != null && stringMatch.DisplayTextPayloads.Any())
{
Identity identity = m_PluginData.GetIdentity(stringMatch.PlayerPayload);
foreach (var customTagId in identity.CustomTagIds)
@@ -252,10 +292,10 @@ namespace PlayerTags.Features
}
void applyTextFormatting(Tag tag)
=> ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.PreferredPayload);
=> ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.DisplayTextPayloads);
}
ApplyStringChanges(message, stringChanges, stringMatch.PreferredPayload);
ApplyStringChanges(message, stringChanges, stringMatch.DisplayTextPayloads, stringMatch.PlayerNamePayload);
}
// Replace PlayerPayloads of your own character with TextPayloads

View File

@@ -33,12 +33,12 @@ namespace PlayerTags.Features
{
if (m_PluginConfiguration.GeneralOptions[activityContextManager.CurrentActivityContext].IsLinkSelfInChatEnabled)
{
ParsePayloads(sender);
ParsePayloads(message);
ParsePayloads(sender, type, true);
ParsePayloads(message, type, false);
}
}
private void ParsePayloads(SeString seString)
private void ParsePayloads(SeString seString, XivChatType chatType, bool isSender)
{
if (PluginServices.ClientState.LocalPlayer != null)
{
@@ -101,7 +101,10 @@ namespace PlayerTags.Features
// For now, don't follow up with a text payload. Only use a player payload.
var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id);
var playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload);
int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload);
if (isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance))
playerPayloadIndex--;
// Add the Player Link Payload
seString.Payloads.Insert(playerPayloadIndex++, playerPayload);

View File

@@ -240,7 +240,7 @@ namespace PlayerTags.Features
/// <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, Dictionary<TagPosition, List<Payload>> stringChanges, Payload? anchorPayload = null)
protected void ApplyStringChanges(SeString seString, Dictionary<TagPosition, List<Payload>> stringChanges, List<Payload> anchorPayloads = null, Payload anchorReplacePayload = null)
{
if (stringChanges.Count == 0)
{
@@ -249,7 +249,7 @@ namespace PlayerTags.Features
List<TagPosition> tagPositionsOrdered = new List<TagPosition>();
// If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data
if (anchorPayload == null)
if (anchorPayloads == null || !anchorPayloads.Any())
{
tagPositionsOrdered.Add(TagPosition.Replace);
}
@@ -258,7 +258,7 @@ namespace PlayerTags.Features
tagPositionsOrdered.Add(TagPosition.After);
// If there is an anchor payload, do replaces last so that we still know which payload needs to be removed
if (anchorPayload != null)
if (anchorPayloads != null && anchorPayloads.Any())
{
tagPositionsOrdered.Add(TagPosition.Replace);
}
@@ -270,8 +270,9 @@ namespace PlayerTags.Features
AddSpacesBetweenTextPayloads(stringChanges[tagPosition], tagPosition);
if (tagPosition == TagPosition.Before)
{
if (anchorPayload != null)
if (anchorPayloads != null && anchorPayloads.Any())
{
var anchorPayload = anchorPayloads.First();
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorPayload);
seString.Payloads.InsertRange(anchorPayloadIndex, payloads);
}
@@ -282,8 +283,9 @@ namespace PlayerTags.Features
}
else if (tagPosition == TagPosition.After)
{
if (anchorPayload != null)
if (anchorPayloads != null && anchorPayloads.Any())
{
var anchorPayload = anchorPayloads.Last();
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorPayload);
seString.Payloads.InsertRange(anchorPayloadIndex + 1, payloads);
}
@@ -294,11 +296,11 @@ namespace PlayerTags.Features
}
else if (tagPosition == TagPosition.Replace)
{
if (anchorPayload != null)
if (anchorReplacePayload != null)
{
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorPayload);
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorReplacePayload);
seString.Payloads.InsertRange(anchorPayloadIndex, payloads);
seString.Payloads.Remove(anchorPayload);
seString.Payloads.Remove(anchorReplacePayload);
}
else
{
@@ -310,7 +312,7 @@ namespace PlayerTags.Features
}
}
protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue<bool>[] textColorApplied, Payload preferedPayload)
protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue<bool>[] textColorApplied, List<Payload> preferedPayloads)
{
if (IsTagVisible(tag, gameObject))
{
@@ -355,10 +357,10 @@ namespace PlayerTags.Features
void applyTextFormattingPayloads(SeString destPayload, Payload startPayload, Payload endPayload)
{
if (preferedPayload == null)
if (preferedPayloads == null || !preferedPayloads.Any())
applyTextFormattingPayloadToStartAndEnd(destPayload, startPayload, endPayload);
else
applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayload);
applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayloads);
}
void applyTextFormattingPayloadToStartAndEnd(SeString destPayload, Payload startPayload, Payload endPayload)
@@ -367,11 +369,13 @@ namespace PlayerTags.Features
destPayload.Payloads.Add(endPayload);
}
void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, Payload preferedPayload)
void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, List<Payload> preferedPayload)
{
int payloadIndex = destPayload.Payloads.IndexOf(preferedPayload);
destPayload.Payloads.Insert(payloadIndex + 1, endPayload);
destPayload.Payloads.Insert(payloadIndex, startPayload);
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);
}
}
}