From 1d672d25520f4aee9b6c2b88ee486d82e821967a Mon Sep 17 00:00:00 2001 From: azyges <229218900+azyges@users.noreply.github.com> Date: Thu, 6 Nov 2025 23:40:58 +0900 Subject: [PATCH] improve checks and add logging --- LightlessSync/Services/NameplateHandler.cs | 94 ++++++++++++++++++---- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/LightlessSync/Services/NameplateHandler.cs b/LightlessSync/Services/NameplateHandler.cs index 5e83683..11af974 100644 --- a/LightlessSync/Services/NameplateHandler.cs +++ b/LightlessSync/Services/NameplateHandler.cs @@ -1,5 +1,6 @@ using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; +using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.Text; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.System.Framework; @@ -15,6 +16,7 @@ using LightlessSync.UtilsEnum.Enum; // Created using https://github.com/PunishedPineapple/Distance as a reference, thank you! using Microsoft.Extensions.Logging; +using System.Collections.Generic; using System.Collections.Immutable; using System.Globalization; @@ -114,6 +116,12 @@ public unsafe class NameplateHandler : IMediatorSubscriber private void NameplateDrawDetour(AddonEvent type, AddonArgs args) { + if (args.Addon.Address == nint.Zero) + { + _logger.LogWarning("Nameplate draw detour received a null addon address, skipping update."); + return; + } + var pNameplateAddon = (AddonNamePlate*)args.Addon.Address; if (_mpNameplateAddon != pNameplateAddon) @@ -138,6 +146,10 @@ public unsafe class NameplateHandler : IMediatorSubscriber if (nameplateObject == null) continue; + var rootNode = nameplateObject.Value.RootComponentNode; + if (rootNode == null || rootNode->Component == null) + continue; + var pNameplateResNode = nameplateObject.Value.NameContainer; if (pNameplateResNode == null) continue; @@ -153,7 +165,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber pNewNode->AtkResNode.NextSiblingNode = pLastChild; pNewNode->AtkResNode.ParentNode = pNameplateResNode; pLastChild->PrevSiblingNode = (AtkResNode*)pNewNode; - nameplateObject.Value.RootComponentNode->Component->UldManager.UpdateDrawNodeList(); + rootNode->Component->UldManager.UpdateDrawNodeList(); pNewNode->AtkResNode.SetUseDepthBasedPriority(true); _mTextNodes[i] = pNewNode; } @@ -162,15 +174,34 @@ public unsafe class NameplateHandler : IMediatorSubscriber private void DestroyNameplateNodes() { - var pCurrentNameplateAddon = (AddonNamePlate*)_gameGui.GetAddonByName("NamePlate", 1).Address; - if (_mpNameplateAddon == null || _mpNameplateAddon != pCurrentNameplateAddon) + var currentHandle = _gameGui.GetAddonByName("NamePlate", 1); + if (currentHandle.Address == nint.Zero) + { + _logger.LogWarning("Unable to destroy nameplate nodes because the NamePlate addon is not available."); return; + } + + var pCurrentNameplateAddon = (AddonNamePlate*)currentHandle.Address; + if (_mpNameplateAddon == null) + return; + + if (_mpNameplateAddon != pCurrentNameplateAddon) + { + _logger.LogWarning("Skipping nameplate node destroy due to addon address mismatch (cached {Cached:X}, current {Current:X}).", (IntPtr)_mpNameplateAddon, (IntPtr)pCurrentNameplateAddon); + return; + } for (int i = 0; i < AddonNamePlate.NumNamePlateObjects; ++i) { var pTextNode = _mTextNodes[i]; var pNameplateNode = GetNameplateComponentNode(i); - if (pTextNode != null && pNameplateNode != null) + if (pTextNode != null && (pNameplateNode == null || pNameplateNode->Component == null)) + { + _logger.LogDebug("Skipping destroy for nameplate {Index} because its component node is unavailable.", i); + continue; + } + + if (pTextNode != null && pNameplateNode != null && pNameplateNode->Component != null) { try { @@ -205,20 +236,48 @@ public unsafe class NameplateHandler : IMediatorSubscriber private void UpdateNameplateNodes() { - var currentAddon = (AddonNamePlate*)_gameGui.GetAddonByName("NamePlate").Address; - if (_mpNameplateAddon == null || currentAddon == null || currentAddon != _mpNameplateAddon) + var currentHandle = _gameGui.GetAddonByName("NamePlate"); + if (currentHandle.Address == nint.Zero) + { + _logger.LogDebug("NamePlate addon unavailable during update, skipping label refresh."); return; + } + + var currentAddon = (AddonNamePlate*)currentHandle.Address; + if (_mpNameplateAddon == null || currentAddon == null || currentAddon != _mpNameplateAddon) + { + if (_mpNameplateAddon != null) + _logger.LogDebug("Cached NamePlate addon pointer differs from current: waiting for new hook (cached {Cached:X}, current {Current:X}).", (IntPtr)_mpNameplateAddon, (IntPtr)currentAddon); + return; + } var framework = Framework.Instance(); - - var ui3DModule = framework->GetUIModule()->GetUI3DModule(); - if (ui3DModule == null) + if (framework == null) + { + _logger.LogDebug("Framework instance unavailable during nameplate update, skipping."); return; + } + + var uiModule = framework->GetUIModule(); + if (uiModule == null) + { + _logger.LogDebug("UI module unavailable during nameplate update, skipping."); + return; + } + + var ui3DModule = uiModule->GetUI3DModule(); + if (ui3DModule == null) + { + _logger.LogDebug("UI3D module unavailable during nameplate update, skipping."); + return; + } var vec = ui3DModule->NamePlateObjectInfoPointers; if (vec.IsEmpty) return; + var visibleUserIdsSnapshot = VisibleUserIds; + var safeCount = System.Math.Min( ui3DModule->NamePlateObjectInfoCount, vec.Length @@ -244,8 +303,15 @@ public unsafe class NameplateHandler : IMediatorSubscriber if (pNode == null) continue; + var gameObject = objectInfo->GameObject; + if ((ObjectKind)gameObject->ObjectKind != ObjectKind.Player) + { + pNode->AtkResNode.ToggleVisibility(enable: false); + continue; + } + // CID gating - var cid = DalamudUtilService.GetHashedCIDFromPlayerPointer((nint)objectInfo->GameObject); + var cid = DalamudUtilService.GetHashedCIDFromPlayerPointer((nint)gameObject); if (cid == null || !_activeBroadcastingCids.Contains(cid)) { pNode->AtkResNode.ToggleVisibility(enable: false); @@ -260,11 +326,10 @@ public unsafe class NameplateHandler : IMediatorSubscriber continue; } - var visibleUserIds = VisibleUserIds; var hidePaired = !config.LightfinderLabelShowPaired; - var goId = (ulong)objectInfo->GameObject->GetGameObjectId(); - if (hidePaired && visibleUserIds.Contains(goId)) + var goId = (ulong)gameObject->GetGameObjectId(); + if (hidePaired && visibleUserIdsSnapshot.Contains(goId)) { pNode->AtkResNode.ToggleVisibility(enable: false); continue; @@ -276,8 +341,9 @@ public unsafe class NameplateHandler : IMediatorSubscriber var nameText = nameplateObject.NameText; var marker = nameplateObject.MarkerIcon; - if (root == null || nameContainer == null || nameText == null) + if (root == null || root->Component == null || nameContainer == null || nameText == null) { + _logger.LogDebug("Nameplate {Index} missing required nodes during update, skipping.", nameplateIndex); pNode->AtkResNode.ToggleVisibility(enable: false); continue; }