Merge pull request #99

fix: censor abbreviated player names in screenshot mode
This commit is contained in:
Infi
2024-07-22 19:17:32 +02:00
committed by GitHub
2 changed files with 66 additions and 4 deletions
+46
View File
@@ -3,6 +3,7 @@ using ChatTwo.Code;
using ChatTwo.GameFunctions.Types; using ChatTwo.GameFunctions.Types;
using ChatTwo.Resources; using ChatTwo.Resources;
using ChatTwo.Util; using ChatTwo.Util;
using Dalamud.Game.Config;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Memory; using Dalamud.Memory;
@@ -57,6 +58,17 @@ internal sealed unsafe class Chat : IDisposable
internal bool UsesTellTempChannel { get; set; } internal bool UsesTellTempChannel { get; set; }
internal InputChannel? PreviousChannel { get; private set; } internal InputChannel? PreviousChannel { get; private set; }
private enum PlayerNameDisplayType : uint
{
FullName = 0,
SurnameAbbreviated = 1,
ForenameAbbreviated = 2,
Initials = 3
}
private long LastPlayerNameDisplayTypeRefresh;
private PlayerNameDisplayType CurrentPlayerNameDisplayType = PlayerNameDisplayType.FullName;
internal Chat(Plugin plugin) internal Chat(Plugin plugin)
{ {
Plugin = plugin; Plugin = plugin;
@@ -444,4 +456,38 @@ internal sealed unsafe class Chat : IDisposable
return wasValid; return wasValid;
} }
private PlayerNameDisplayType GetNameDisplayType()
{
var ok = Plugin.GameConfig.TryGet(UiConfigOption.LogNameType, out uint type);
if (!ok || !Enum.IsDefined(typeof(PlayerNameDisplayType), type))
return PlayerNameDisplayType.FullName;
return (PlayerNameDisplayType) type;
}
internal string AbbreviatePlayerName(string playerName)
{
if (LastPlayerNameDisplayTypeRefresh + 5 * 1000 < Environment.TickCount64)
{
LastPlayerNameDisplayTypeRefresh = Environment.TickCount64;
CurrentPlayerNameDisplayType = GetNameDisplayType();
}
if (CurrentPlayerNameDisplayType == PlayerNameDisplayType.FullName)
return playerName;
var split = playerName.Split(' ');
if (split.Length != 2)
return playerName;
return CurrentPlayerNameDisplayType switch
{
PlayerNameDisplayType.SurnameAbbreviated =>
$"{split.First()} {split.Last().FirstOrDefault('A')}.",
PlayerNameDisplayType.ForenameAbbreviated =>
$"{split.First().FirstOrDefault('A')}. {split.Last()}",
PlayerNameDisplayType.Initials =>
$"{split.First().FirstOrDefault('A')}. {split.Last().FirstOrDefault('A')}.",
_ => playerName
};
}
} }
+20 -4
View File
@@ -546,6 +546,8 @@ public sealed class ChatLogWindow : Window
{ {
var playerName = TellTarget.Name; var playerName = TellTarget.Name;
if (ScreenshotMode) if (ScreenshotMode)
// Note: don't use HidePlayerInString here because
// abbreviation settings do not affect this.
playerName = HashPlayer(TellTarget.Name, TellTarget.World); playerName = HashPlayer(TellTarget.Name, TellTarget.World);
var world = WorldSheet.GetRow(TellTarget.World)?.Name?.RawString ?? "???"; var world = WorldSheet.GetRow(TellTarget.World)?.Name?.RawString ?? "???";
@@ -594,6 +596,8 @@ public sealed class ChatLogWindow : Window
{ {
if (!string.IsNullOrWhiteSpace(tellPlayerName) && tellWorldId != 0) if (!string.IsNullOrWhiteSpace(tellPlayerName) && tellWorldId != 0)
{ {
// Note: don't use HidePlayerInString here because
// abbreviation settings do not affect this.
var playerName = HashPlayer(tellPlayerName, tellWorldId); var playerName = HashPlayer(tellPlayerName, tellWorldId);
var world = WorldSheet.GetRow(tellWorldId)?.Name?.RawString ?? "???"; var world = WorldSheet.GetRow(tellWorldId)?.Name?.RawString ?? "???";
@@ -1648,10 +1652,14 @@ public sealed class ChatLogWindow : Window
var content = text.Content ?? ""; var content = text.Content ?? "";
if (ScreenshotMode) if (ScreenshotMode)
{ {
if (chunk.Link is PlayerPayload playerPayload && content.Contains(playerPayload.PlayerName)) // TODO: the result of hashing the player name should be cached.
content = content.Replace(playerPayload.PlayerName, HashPlayer(playerPayload.PlayerName, playerPayload.World.RowId)); // Currently we recalculate the abbreviated player names, the
else if (Plugin.ClientState.LocalPlayer is { } player && content.Contains(player.Name.TextValue)) // hashes and the string replacements every frame when they
content = content.Replace(player.Name.TextValue, HashPlayer(player.Name.TextValue, player.HomeWorld.Id)); // never change.
if (chunk.Link is PlayerPayload playerPayload)
content = HidePlayerInString(content, playerPayload.PlayerName, playerPayload.World.RowId);
else if (Plugin.ClientState.LocalPlayer is { } player)
content = HidePlayerInString(content, player.Name.TextValue, player.HomeWorld.Id);
} }
if (wrap) if (wrap)
@@ -1683,6 +1691,14 @@ public sealed class ChatLogWindow : Window
ImGui.Image(FontIcon.ImGuiHandle, size, uv0, uv1); ImGui.Image(FontIcon.ImGuiHandle, size, uv0, uv1);
ImGuiUtil.PostPayload(chunk, handler); ImGuiUtil.PostPayload(chunk, handler);
}
private string HidePlayerInString(string str, string playerName, uint worldId)
{
var expected = Plugin.Functions.Chat.AbbreviatePlayerName(playerName);
var hash = HashPlayer(playerName, worldId);
return str.Replace(playerName, expected).Replace(expected, hash);
} }
private string HashPlayer(string playerName, uint worldId) private string HashPlayer(string playerName, uint worldId)