NominaOcculta/NominaOcculta/Obscurer.cs

169 lines
6.4 KiB
C#
Executable File

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Dalamud.Game;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using XivCommon.Functions.NamePlates;
namespace NominaOcculta {
internal class Obscurer : IDisposable {
private Plugin Plugin { get; }
private Stopwatch UpdateTimer { get; } = new();
private IList<string> Friends { get; set; }
internal Obscurer(Plugin plugin) {
this.Plugin = plugin;
this.UpdateTimer.Start();
this.Friends = this.Plugin.Common.Functions.FriendList.List
.Select(friend => friend.Name.TextValue)
.ToList();
this.Plugin.Framework.Update += this.OnFrameworkUpdate;
this.Plugin.Functions.AtkTextNodeSetText += this.OnAtkTextNodeSetText;
this.Plugin.Common.Functions.NamePlates.OnUpdate += this.OnNamePlateUpdate;
this.Plugin.ChatGui.ChatMessage += this.OnChatMessage;
}
public void Dispose() {
this.Plugin.ChatGui.ChatMessage -= this.OnChatMessage;
this.Plugin.Common.Functions.NamePlates.OnUpdate -= this.OnNamePlateUpdate;
this.Plugin.Functions.AtkTextNodeSetText -= this.OnAtkTextNodeSetText;
this.Plugin.Framework.Update -= this.OnFrameworkUpdate;
}
private void OnFrameworkUpdate(Framework framework) {
if (this.UpdateTimer.Elapsed < TimeSpan.FromSeconds(5)) {
return;
}
this.Friends = this.Plugin.Common.Functions.FriendList.List
.Select(friend => friend.Name.TextValue)
.ToList();
this.UpdateTimer.Restart();
}
private void OnAtkTextNodeSetText(IntPtr node, IntPtr textPtr, ref SeString? overwrite) {
// A catch-all for UI text. This is slow, so specialised methods should be preferred.
var text = Util.ReadRawSeString(textPtr);
var changed = this.ChangeNames(text);
if (changed) {
overwrite = text;
}
}
private void OnNamePlateUpdate(NamePlateUpdateEventArgs args) {
this.ChangeNames(args.Name);
this.ChangeNames(args.Title); // for minions
}
private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) {
this.ChangeNames(sender);
this.ChangeNames(message);
}
private bool ChangeNames(SeString text) {
if (!this.Plugin.Config.Enabled || !this.Plugin.NameRepository.Initialised) {
return false;
}
var changed = false;
var player = this.Plugin.ClientState.LocalPlayer;
if (this.Plugin.Config.SelfFull) {
var playerName = player?.Name.TextValue;
if (playerName != null && text.ContainsPlayerName(playerName) && this.Plugin.NameRepository.GetReplacement(playerName, GetInfo(player!)) is { } replacement) {
text.ReplacePlayerName(playerName, replacement);
changed = true;
}
}
if (this.Plugin.Config.SelfFirst || this.Plugin.Config.SelfLast) {
var playerName = player?.Name.TextValue;
if (playerName != null && this.Plugin.NameRepository.GetReplacement(playerName, GetInfo(player!)) is { } replacement) {
var parts = playerName.Split(' ', 2);
var replacementParts = replacement.Split(' ', 2);
if (this.Plugin.Config.SelfFirst && text.ContainsPlayerName(parts[0])) {
text.ReplacePlayerName(parts[0], replacementParts[0]);
changed = true;
}
if (this.Plugin.Config.SelfLast && text.ContainsPlayerName(parts[1])) {
text.ReplacePlayerName(parts[1], replacementParts[1]);
changed = true;
}
}
}
if (this.Plugin.Config.Party) {
foreach (var member in this.Plugin.PartyList) {
var name = member.Name.TextValue;
var info = ((byte) 0xFF, (byte) 0xFF, member.Sex);
if (member.GameObject is Character chara) {
info = GetInfo(chara);
}
if (member.ObjectId == player?.ObjectId || !text.ContainsPlayerName(name) || this.Plugin.NameRepository.GetReplacement(name, info) is not { } replacement) {
continue;
}
if (this.Plugin.Config.ExcludeFriends && this.Friends.Contains(name)) {
continue;
}
text.ReplacePlayerName(name, replacement);
changed = true;
}
}
if (this.Plugin.Config.Others) {
var party = this.Plugin.PartyList.Select(member => member.ObjectId).ToList();
foreach (var obj in this.Plugin.ObjectTable) {
if (obj.ObjectKind != ObjectKind.Player || obj is not Character chara || obj.ObjectId == player?.ObjectId || party.Contains(obj.ObjectId)) {
continue;
}
var name = chara.Name.TextValue;
if (this.Plugin.Config.ExcludeFriends && this.Friends.Contains(name)) {
continue;
}
var info = GetInfo(chara);
if (info.race == 0) {
continue;
}
if (this.Plugin.NameRepository.GetReplacement(name, GetInfo(chara)) is not { } replacement) {
continue;
}
text.ReplacePlayerName(name, replacement);
changed = true;
}
}
return changed;
}
private static (byte race, byte clan, byte gender) GetInfo(Character chara) {
return (
chara.Customize[(byte) CustomizeIndex.Race],
(byte) ((chara.Customize[(byte) CustomizeIndex.Tribe] - 1) % 2),
chara.Customize[(byte) CustomizeIndex.Gender]
);
}
}
}