145 lines
5.5 KiB
C#
145 lines
5.5 KiB
C#
![]() |
using Dalamud.Game.Gui.NamePlate;
|
||
|
using Dalamud.Game.Text.SeStringHandling;
|
||
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||
|
using Dalamud.Plugin.Services;
|
||
|
using MareSynchronos.MareConfiguration;
|
||
|
using MareSynchronos.PlayerData.Pairs;
|
||
|
using MareSynchronos.Services.Mediator;
|
||
|
using MareSynchronos.UI;
|
||
|
using Microsoft.Extensions.Logging;
|
||
|
|
||
|
namespace MareSynchronos.Services;
|
||
|
|
||
|
public class GuiHookService : DisposableMediatorSubscriberBase
|
||
|
{
|
||
|
private readonly ILogger<GuiHookService> _logger;
|
||
|
private readonly DalamudUtilService _dalamudUtil;
|
||
|
private readonly MareConfigService _configService;
|
||
|
private readonly INamePlateGui _namePlateGui;
|
||
|
private readonly IGameConfig _gameConfig;
|
||
|
private readonly IPartyList _partyList;
|
||
|
private readonly PairManager _pairManager;
|
||
|
|
||
|
private bool _isModified = false;
|
||
|
private bool _namePlateRoleColorsEnabled = false;
|
||
|
|
||
|
public GuiHookService(ILogger<GuiHookService> logger, DalamudUtilService dalamudUtil, MareMediator mediator, MareConfigService configService,
|
||
|
INamePlateGui namePlateGui, IGameConfig gameConfig, IPartyList partyList, PairManager pairManager)
|
||
|
: base(logger, mediator)
|
||
|
{
|
||
|
_logger = logger;
|
||
|
_dalamudUtil = dalamudUtil;
|
||
|
_configService = configService;
|
||
|
_namePlateGui = namePlateGui;
|
||
|
_gameConfig = gameConfig;
|
||
|
_partyList = partyList;
|
||
|
_pairManager = pairManager;
|
||
|
|
||
|
_namePlateGui.OnNamePlateUpdate += OnNamePlateUpdate;
|
||
|
_namePlateGui.RequestRedraw();
|
||
|
|
||
|
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => GameSettingsCheck());
|
||
|
Mediator.Subscribe<PairHandlerVisibleMessage>(this, (_) => RequestRedraw());
|
||
|
Mediator.Subscribe<NameplateRedrawMessage>(this, (_) => RequestRedraw());
|
||
|
}
|
||
|
|
||
|
public void RequestRedraw(bool force = false)
|
||
|
{
|
||
|
if (!_configService.Current.UseNameColors)
|
||
|
{
|
||
|
if (!_isModified && !force)
|
||
|
return;
|
||
|
_isModified = false;
|
||
|
}
|
||
|
|
||
|
_ = Task.Run(async () => {
|
||
|
await _dalamudUtil.RunOnFrameworkThread(() => _namePlateGui.RequestRedraw()).ConfigureAwait(false);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
protected override void Dispose(bool disposing)
|
||
|
{
|
||
|
base.Dispose(disposing);
|
||
|
_namePlateGui.OnNamePlateUpdate -= OnNamePlateUpdate;
|
||
|
|
||
|
_ = Task.Run(async () => {
|
||
|
await _dalamudUtil.RunOnFrameworkThread(() => _namePlateGui.RequestRedraw()).ConfigureAwait(false);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private void OnNamePlateUpdate(INamePlateUpdateContext context, IReadOnlyList<INamePlateUpdateHandler> handlers)
|
||
|
{
|
||
|
if (!_configService.Current.UseNameColors)
|
||
|
return;
|
||
|
|
||
|
var visibleUsers = _pairManager.GetOnlineUserPairs().Where(u => u.IsVisible && u.PlayerCharacterId != uint.MaxValue);
|
||
|
var visibleUsersIds = visibleUsers.Select(u => (ulong)u.PlayerCharacterId).ToHashSet();
|
||
|
|
||
|
var visibleUsersDict = visibleUsers.ToDictionary(u => (ulong)u.PlayerCharacterId);
|
||
|
|
||
|
var partyMembers = new nint[_partyList.Count];
|
||
|
|
||
|
for (int i = 0; i < _partyList.Count; ++i)
|
||
|
partyMembers[i] = _partyList[i]?.GameObject?.Address ?? nint.MaxValue;
|
||
|
|
||
|
foreach (var handler in handlers)
|
||
|
{
|
||
|
if (handler != null && visibleUsersIds.Contains(handler.GameObjectId))
|
||
|
{
|
||
|
if (_namePlateRoleColorsEnabled && partyMembers.Contains(handler.GameObject?.Address ?? nint.MaxValue))
|
||
|
continue;
|
||
|
var pair = visibleUsersDict[handler.GameObjectId];
|
||
|
var colors = !pair.IsApplicationBlocked ? _configService.Current.NameColors : _configService.Current.BlockedNameColors;
|
||
|
handler.NameParts.TextWrap = (
|
||
|
BuildColorStartSeString(colors),
|
||
|
BuildColorEndSeString(colors)
|
||
|
);
|
||
|
_isModified = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void GameSettingsCheck()
|
||
|
{
|
||
|
if (!_gameConfig.TryGet(Dalamud.Game.Config.UiConfigOption.NamePlateSetRoleColor, out bool namePlateRoleColorsEnabled))
|
||
|
return;
|
||
|
|
||
|
if (_namePlateRoleColorsEnabled != namePlateRoleColorsEnabled)
|
||
|
{
|
||
|
_namePlateRoleColorsEnabled = namePlateRoleColorsEnabled;
|
||
|
RequestRedraw(force: true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#region Colored SeString
|
||
|
private const byte _colorTypeForeground = 0x13;
|
||
|
private const byte _colorTypeGlow = 0x14;
|
||
|
|
||
|
private static SeString BuildColorStartSeString(DtrEntry.Colors colors)
|
||
|
{
|
||
|
var ssb = new SeStringBuilder();
|
||
|
if (colors.Foreground != default)
|
||
|
ssb.Add(BuildColorStartPayload(_colorTypeForeground, colors.Foreground));
|
||
|
if (colors.Glow != default)
|
||
|
ssb.Add(BuildColorStartPayload(_colorTypeGlow, colors.Glow));
|
||
|
return ssb.Build();
|
||
|
}
|
||
|
|
||
|
private static SeString BuildColorEndSeString(DtrEntry.Colors colors)
|
||
|
{
|
||
|
var ssb = new SeStringBuilder();
|
||
|
if (colors.Glow != default)
|
||
|
ssb.Add(BuildColorEndPayload(_colorTypeGlow));
|
||
|
if (colors.Foreground != default)
|
||
|
ssb.Add(BuildColorEndPayload(_colorTypeForeground));
|
||
|
return ssb.Build();
|
||
|
}
|
||
|
|
||
|
private static RawPayload BuildColorStartPayload(byte colorType, uint color)
|
||
|
=> new(unchecked([0x02, colorType, 0x05, 0xF6, byte.Max((byte)color, 0x01), byte.Max((byte)(color >> 8), 0x01), byte.Max((byte)(color >> 16), 0x01), 0x03]));
|
||
|
|
||
|
private static RawPayload BuildColorEndPayload(byte colorType)
|
||
|
=> new([0x02, colorType, 0x02, 0xEC, 0x03]);
|
||
|
#endregion
|
||
|
}
|