From 18ece74c6d309293dbaf44cffa427a1cf7749abf Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Tue, 29 Oct 2024 21:38:19 +0100 Subject: [PATCH] do not handle blocked/muted characters --- .../Interop/BlockedCharacterHandler.cs | 58 +++++++++++++++++++ MareSynchronos/Plugin.cs | 5 +- MareSynchronos/Services/DalamudUtilService.cs | 9 ++- 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 MareSynchronos/Interop/BlockedCharacterHandler.cs diff --git a/MareSynchronos/Interop/BlockedCharacterHandler.cs b/MareSynchronos/Interop/BlockedCharacterHandler.cs new file mode 100644 index 0000000..17a45fd --- /dev/null +++ b/MareSynchronos/Interop/BlockedCharacterHandler.cs @@ -0,0 +1,58 @@ +using Dalamud.Plugin.Services; +using Dalamud.Utility.Signatures; +using FFXIVClientStructs.FFXIV.Client.Game.Character; +using FFXIVClientStructs.FFXIV.Client.UI.Info; +using Microsoft.Extensions.Logging; + +namespace MareSynchronos.Interop; + +public unsafe class BlockedCharacterHandler +{ + private readonly Dictionary<(ulong, ulong), bool> _blockedCharacterCache = new(); + + private enum BlockResultType + { + NotBlocked = 1, + BlockedByAccountId = 2, + BlockedByContentId = 3, + } + + [Signature("48 83 EC 48 F6 81 ?? ?? ?? ?? ?? 75 ?? 33 C0 48 83 C4 48")] + private readonly GetBlockResultTypeDelegate? _getBlockResultType = null; + private readonly ILogger _logger; + + private unsafe delegate BlockResultType GetBlockResultTypeDelegate(InfoProxyBlacklist* thisPtr, ulong accountId, ulong contentId); + + public BlockedCharacterHandler(ILogger logger, IGameInteropProvider gameInteropProvider) + { + gameInteropProvider.InitializeFromAttributes(this); + _logger = logger; + } + + private static ulong GetAccIdFromPlayerPointer(nint ptr) + { + if (ptr == nint.Zero) return 0; + return ((BattleChara*)ptr)->Character.AccountId; + } + + private static ulong GetContentIdFromPlayerPointer(nint ptr) + { + if (ptr == nint.Zero) return 0; + return ((BattleChara*)ptr)->Character.ContentId; + } + + public bool IsCharacterBlocked(nint ptr) + { + (ulong AccId, ulong ContentId) combined = (GetAccIdFromPlayerPointer(ptr), GetContentIdFromPlayerPointer(ptr)); + if (_blockedCharacterCache.TryGetValue(combined, out var isBlocked)) + return isBlocked; + + if (_getBlockResultType == null) + return _blockedCharacterCache[combined] = false; + + var infoProxy = InfoProxyBlacklist.Instance(); + var blockStatus = _getBlockResultType(infoProxy, combined.AccId, combined.ContentId); + _logger.LogTrace("CharaPtr {ptr} is BlockStatus: {status}", ptr, blockStatus); + return _blockedCharacterCache[combined] = blockStatus != BlockResultType.NotBlocked; + } +} diff --git a/MareSynchronos/Plugin.cs b/MareSynchronos/Plugin.cs index e57f3dc..434c391 100644 --- a/MareSynchronos/Plugin.cs +++ b/MareSynchronos/Plugin.cs @@ -36,7 +36,7 @@ public sealed class Plugin : IDalamudPlugin public Plugin(IDalamudPluginInterface pluginInterface, ICommandManager commandManager, IDataManager gameData, IFramework framework, IObjectTable objectTable, IClientState clientState, ICondition condition, IChatGui chatGui, IGameGui gameGui, IDtrBar dtrBar, IPluginLog pluginLog, ITargetManager targetManager, INotificationManager notificationManager, - ITextureProvider textureProvider, IContextMenu contextMenu) + ITextureProvider textureProvider, IContextMenu contextMenu, IGameInteropProvider gameInteropProvider) { if (!Directory.Exists(pluginInterface.ConfigDirectory.FullName)) Directory.CreateDirectory(pluginInterface.ConfigDirectory.FullName); @@ -110,6 +110,7 @@ public sealed class Plugin : IDalamudPlugin collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(); + collection.AddSingleton((s) => new BlockedCharacterHandler(s.GetRequiredService>(), gameInteropProvider)); collection.AddSingleton((s) => new IpcProvider(s.GetRequiredService>(), pluginInterface, s.GetRequiredService(), s.GetRequiredService(), @@ -119,7 +120,7 @@ public sealed class Plugin : IDalamudPlugin s.GetRequiredService>(), s.GetRequiredService())); collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService>(), clientState, objectTable, framework, gameGui, condition, gameData, targetManager, - s.GetRequiredService(), s.GetRequiredService())); + s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton((s) => new DtrEntry(s.GetRequiredService>(), dtrBar, s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton(s => new PairManager(s.GetRequiredService>(), s.GetRequiredService(), diff --git a/MareSynchronos/Services/DalamudUtilService.cs b/MareSynchronos/Services/DalamudUtilService.cs index 1f9cbd5..211a878 100644 --- a/MareSynchronos/Services/DalamudUtilService.cs +++ b/MareSynchronos/Services/DalamudUtilService.cs @@ -6,6 +6,7 @@ using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Control; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; +using MareSynchronos.Interop; using MareSynchronos.PlayerData.Handlers; using MareSynchronos.Services.Mediator; using MareSynchronos.Utils; @@ -23,6 +24,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber private readonly IClientState _clientState; private readonly ICondition _condition; private readonly IDataManager _gameData; + private readonly BlockedCharacterHandler _blockedCharacterHandler; private readonly IFramework _framework; private readonly IGameGui _gameGui; private readonly ILogger _logger; @@ -37,9 +39,10 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber private readonly List _notUpdatedCharas = []; private bool _sentBetweenAreas = false; + public DalamudUtilService(ILogger logger, IClientState clientState, IObjectTable objectTable, IFramework framework, IGameGui gameGui, ICondition condition, IDataManager gameData, ITargetManager targetManager, - MareMediator mediator, PerformanceCollectorService performanceCollector) + BlockedCharacterHandler blockedCharacterHandler, MareMediator mediator, PerformanceCollectorService performanceCollector) { _logger = logger; _clientState = clientState; @@ -48,6 +51,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber _gameGui = gameGui; _condition = condition; _gameData = gameData; + _blockedCharacterHandler = blockedCharacterHandler; Mediator = mediator; _performanceCollector = performanceCollector; WorldData = new(() => @@ -457,6 +461,9 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber if (chara == null || chara.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) continue; + if (_blockedCharacterHandler.IsCharacterBlocked(chara.Address)) + continue; + var charaName = ((GameObject*)chara.Address)->NameString; var hash = GetHashedAccIdFromPlayerPointer(chara.Address); if (!IsAnythingDrawing)