2.0.0 #92
@@ -1,5 +1,6 @@
|
|||||||
using Dalamud.Game.Addon.Lifecycle;
|
using Dalamud.Game.Addon.Lifecycle;
|
||||||
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||||
|
using Dalamud.Game.ClientState.Objects.Enums;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
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!
|
// Created using https://github.com/PunishedPineapple/Distance as a reference, thank you!
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
@@ -114,6 +116,12 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
|
|
||||||
private void NameplateDrawDetour(AddonEvent type, AddonArgs args)
|
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;
|
var pNameplateAddon = (AddonNamePlate*)args.Addon.Address;
|
||||||
|
|
||||||
if (_mpNameplateAddon != pNameplateAddon)
|
if (_mpNameplateAddon != pNameplateAddon)
|
||||||
@@ -138,6 +146,10 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
if (nameplateObject == null)
|
if (nameplateObject == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
var rootNode = nameplateObject.Value.RootComponentNode;
|
||||||
|
if (rootNode == null || rootNode->Component == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
var pNameplateResNode = nameplateObject.Value.NameContainer;
|
var pNameplateResNode = nameplateObject.Value.NameContainer;
|
||||||
if (pNameplateResNode == null)
|
if (pNameplateResNode == null)
|
||||||
continue;
|
continue;
|
||||||
@@ -153,7 +165,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
pNewNode->AtkResNode.NextSiblingNode = pLastChild;
|
pNewNode->AtkResNode.NextSiblingNode = pLastChild;
|
||||||
pNewNode->AtkResNode.ParentNode = pNameplateResNode;
|
pNewNode->AtkResNode.ParentNode = pNameplateResNode;
|
||||||
pLastChild->PrevSiblingNode = (AtkResNode*)pNewNode;
|
pLastChild->PrevSiblingNode = (AtkResNode*)pNewNode;
|
||||||
nameplateObject.Value.RootComponentNode->Component->UldManager.UpdateDrawNodeList();
|
rootNode->Component->UldManager.UpdateDrawNodeList();
|
||||||
pNewNode->AtkResNode.SetUseDepthBasedPriority(true);
|
pNewNode->AtkResNode.SetUseDepthBasedPriority(true);
|
||||||
_mTextNodes[i] = pNewNode;
|
_mTextNodes[i] = pNewNode;
|
||||||
}
|
}
|
||||||
@@ -162,15 +174,34 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
|
|
||||||
private void DestroyNameplateNodes()
|
private void DestroyNameplateNodes()
|
||||||
{
|
{
|
||||||
var pCurrentNameplateAddon = (AddonNamePlate*)_gameGui.GetAddonByName("NamePlate", 1).Address;
|
var currentHandle = _gameGui.GetAddonByName("NamePlate", 1);
|
||||||
if (_mpNameplateAddon == null || _mpNameplateAddon != pCurrentNameplateAddon)
|
if (currentHandle.Address == nint.Zero)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Unable to destroy nameplate nodes because the NamePlate addon is not available.");
|
||||||
return;
|
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)
|
for (int i = 0; i < AddonNamePlate.NumNamePlateObjects; ++i)
|
||||||
{
|
{
|
||||||
var pTextNode = _mTextNodes[i];
|
var pTextNode = _mTextNodes[i];
|
||||||
var pNameplateNode = GetNameplateComponentNode(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
|
try
|
||||||
{
|
{
|
||||||
@@ -205,20 +236,48 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
|
|
||||||
private void UpdateNameplateNodes()
|
private void UpdateNameplateNodes()
|
||||||
{
|
{
|
||||||
var currentAddon = (AddonNamePlate*)_gameGui.GetAddonByName("NamePlate").Address;
|
var currentHandle = _gameGui.GetAddonByName("NamePlate");
|
||||||
if (_mpNameplateAddon == null || currentAddon == null || currentAddon != _mpNameplateAddon)
|
if (currentHandle.Address == nint.Zero)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("NamePlate addon unavailable during update, skipping label refresh.");
|
||||||
return;
|
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 framework = Framework.Instance();
|
||||||
|
if (framework == null)
|
||||||
var ui3DModule = framework->GetUIModule()->GetUI3DModule();
|
{
|
||||||
if (ui3DModule == null)
|
_logger.LogDebug("Framework instance unavailable during nameplate update, skipping.");
|
||||||
return;
|
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;
|
var vec = ui3DModule->NamePlateObjectInfoPointers;
|
||||||
if (vec.IsEmpty)
|
if (vec.IsEmpty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var visibleUserIdsSnapshot = VisibleUserIds;
|
||||||
|
|
||||||
var safeCount = System.Math.Min(
|
var safeCount = System.Math.Min(
|
||||||
ui3DModule->NamePlateObjectInfoCount,
|
ui3DModule->NamePlateObjectInfoCount,
|
||||||
vec.Length
|
vec.Length
|
||||||
@@ -244,8 +303,15 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
if (pNode == null)
|
if (pNode == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
var gameObject = objectInfo->GameObject;
|
||||||
|
if ((ObjectKind)gameObject->ObjectKind != ObjectKind.Player)
|
||||||
|
{
|
||||||
|
pNode->AtkResNode.ToggleVisibility(enable: false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// CID gating
|
// CID gating
|
||||||
var cid = DalamudUtilService.GetHashedCIDFromPlayerPointer((nint)objectInfo->GameObject);
|
var cid = DalamudUtilService.GetHashedCIDFromPlayerPointer((nint)gameObject);
|
||||||
if (cid == null || !_activeBroadcastingCids.Contains(cid))
|
if (cid == null || !_activeBroadcastingCids.Contains(cid))
|
||||||
{
|
{
|
||||||
pNode->AtkResNode.ToggleVisibility(enable: false);
|
pNode->AtkResNode.ToggleVisibility(enable: false);
|
||||||
@@ -260,11 +326,10 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var visibleUserIds = VisibleUserIds;
|
|
||||||
var hidePaired = !config.LightfinderLabelShowPaired;
|
var hidePaired = !config.LightfinderLabelShowPaired;
|
||||||
|
|
||||||
var goId = (ulong)objectInfo->GameObject->GetGameObjectId();
|
var goId = (ulong)gameObject->GetGameObjectId();
|
||||||
if (hidePaired && visibleUserIds.Contains(goId))
|
if (hidePaired && visibleUserIdsSnapshot.Contains(goId))
|
||||||
{
|
{
|
||||||
pNode->AtkResNode.ToggleVisibility(enable: false);
|
pNode->AtkResNode.ToggleVisibility(enable: false);
|
||||||
continue;
|
continue;
|
||||||
@@ -276,8 +341,9 @@ public unsafe class NameplateHandler : IMediatorSubscriber
|
|||||||
var nameText = nameplateObject.NameText;
|
var nameText = nameplateObject.NameText;
|
||||||
var marker = nameplateObject.MarkerIcon;
|
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);
|
pNode->AtkResNode.ToggleVisibility(enable: false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user