Initialize migration. (#88)

Co-authored-by: defnotken <itsdefnotken@gmail.com>
Co-authored-by: cake <admin@cakeandbanana.nl>
Reviewed-on: #88
Reviewed-by: cake <cake@noreply.git.lightless-sync.org>
Co-authored-by: defnotken <defnotken@noreply.git.lightless-sync.org>
Co-committed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
This commit was merged in pull request #88.
This commit is contained in:
2025-11-29 18:02:39 +01:00
committed by cake
parent 9e12725f89
commit 740b58afc4
63 changed files with 1720 additions and 1005 deletions

View File

@@ -16,7 +16,6 @@ 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;
@@ -28,7 +27,6 @@ public unsafe class NameplateHandler : IMediatorSubscriber
private readonly IAddonLifecycle _addonLifecycle;
private readonly IGameGui _gameGui;
private readonly IClientState _clientState;
private readonly DalamudUtilService _dalamudUtil;
private readonly LightlessConfigService _configService;
private readonly PairUiService _pairUiService;
private readonly LightlessMediator _mediator;
@@ -46,17 +44,15 @@ public unsafe class NameplateHandler : IMediatorSubscriber
internal const uint mNameplateNodeIDBase = 0x7D99D500;
private const string DefaultLabelText = "LightFinder";
private const SeIconChar DefaultIcon = SeIconChar.Hyadelyn;
private const int _containerOffsetX = 50;
private static readonly string DefaultIconGlyph = SeIconCharExtensions.ToIconString(DefaultIcon);
private ImmutableHashSet<string> _activeBroadcastingCids = [];
public NameplateHandler(ILogger<NameplateHandler> logger, IAddonLifecycle addonLifecycle, IGameGui gameGui, DalamudUtilService dalamudUtil, LightlessConfigService configService, LightlessMediator mediator, IClientState clientState, PairUiService pairUiService)
public NameplateHandler(ILogger<NameplateHandler> logger, IAddonLifecycle addonLifecycle, IGameGui gameGui, LightlessConfigService configService, LightlessMediator mediator, IClientState clientState, PairUiService pairUiService)
{
_logger = logger;
_addonLifecycle = addonLifecycle;
_gameGui = gameGui;
_dalamudUtil = dalamudUtil;
_configService = configService;
_mediator = mediator;
_clientState = clientState;
@@ -118,7 +114,8 @@ public unsafe class NameplateHandler : IMediatorSubscriber
{
if (args.Addon.Address == nint.Zero)
{
_logger.LogWarning("Nameplate draw detour received a null addon address, skipping update.");
if (_logger.IsEnabled(LogLevel.Warning))
_logger.LogWarning("Nameplate draw detour received a null addon address, skipping update.");
return;
}
@@ -177,7 +174,8 @@ public unsafe class NameplateHandler : IMediatorSubscriber
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.");
if (_logger.IsEnabled(LogLevel.Warning))
_logger.LogWarning("Unable to destroy nameplate nodes because the NamePlate addon is not available.");
return;
}
@@ -187,7 +185,8 @@ public unsafe class NameplateHandler : IMediatorSubscriber
if (_mpNameplateAddon != pCurrentNameplateAddon)
{
_logger.LogWarning("Skipping nameplate node destroy due to addon address mismatch (cached {Cached:X}, current {Current:X}).", (IntPtr)_mpNameplateAddon, (IntPtr)pCurrentNameplateAddon);
if (_logger.IsEnabled(LogLevel.Warning))
_logger.LogWarning("Skipping nameplate node destroy due to addon address mismatch (cached {Cached}, current {Current}).", (IntPtr)_mpNameplateAddon, (IntPtr)pCurrentNameplateAddon);
return;
}
@@ -197,7 +196,8 @@ public unsafe class NameplateHandler : IMediatorSubscriber
var pNameplateNode = GetNameplateComponentNode(i);
if (pTextNode != null && (pNameplateNode == null || pNameplateNode->Component == null))
{
_logger.LogDebug("Skipping destroy for nameplate {Index} because its component node is unavailable.", i);
if (_logger.IsEnabled(LogLevel.Debug))
_logger.LogDebug("Skipping destroy for nameplate {Index} because its component node is unavailable.", i);
continue;
}
@@ -210,12 +210,13 @@ public unsafe class NameplateHandler : IMediatorSubscriber
if (pTextNode->AtkResNode.NextSiblingNode != null)
pTextNode->AtkResNode.NextSiblingNode->PrevSiblingNode = pTextNode->AtkResNode.PrevSiblingNode;
pNameplateNode->Component->UldManager.UpdateDrawNodeList();
pTextNode->AtkResNode.Destroy(true);
pTextNode->AtkResNode.Destroy(free: true);
_mTextNodes[i] = null;
}
catch (Exception e)
{
_logger.LogError($"Unknown error while removing text node 0x{(IntPtr)pTextNode:X} for nameplate {i} on component node 0x{(IntPtr)pNameplateNode:X}:\n{e}");
if (_logger.IsEnabled(LogLevel.Error))
_logger.LogError("Unknown error while removing text node 0x{textNode} for nameplate {i} on component node 0x{nameplateNode}:\n{e}", (IntPtr)pTextNode, i, (IntPtr)pNameplateNode, e);
}
}
}
@@ -239,36 +240,40 @@ public unsafe class NameplateHandler : IMediatorSubscriber
var currentHandle = _gameGui.GetAddonByName("NamePlate");
if (currentHandle.Address == nint.Zero)
{
_logger.LogDebug("NamePlate addon unavailable during update, skipping label refresh.");
if (_logger.IsEnabled(LogLevel.Debug))
_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);
if (_mpNameplateAddon != null && _logger.IsEnabled(LogLevel.Debug))
_logger.LogDebug("Cached NamePlate addon pointer differs from current: waiting for new hook (cached {Cached}, current {Current}).", (IntPtr)_mpNameplateAddon, (IntPtr)currentAddon);
return;
}
var framework = Framework.Instance();
if (framework == null)
{
_logger.LogDebug("Framework instance unavailable during nameplate update, skipping.");
if (_logger.IsEnabled(LogLevel.Debug))
_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.");
if (_logger.IsEnabled(LogLevel.Debug))
_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.");
if (_logger.IsEnabled(LogLevel.Debug))
_logger.LogDebug("UI3D module unavailable during nameplate update, skipping.");
return;
}
@@ -280,7 +285,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber
var safeCount = System.Math.Min(
ui3DModule->NamePlateObjectInfoCount,
vec.Length
vec.Length
);
for (int i = 0; i < safeCount; ++i)
@@ -347,7 +352,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber
pNode->AtkResNode.ToggleVisibility(enable: false);
continue;
}
root->Component->UldManager.UpdateDrawNodeList();
bool isVisible =
@@ -449,10 +454,6 @@ public unsafe class NameplateHandler : IMediatorSubscriber
{
_cachedNameplateTextOffsets[nameplateIndex] = textOffset;
}
else if (_cachedNameplateTextOffsets[nameplateIndex] != int.MinValue)
{
textOffset = _cachedNameplateTextOffsets[nameplateIndex];
}
else
{
hasValidOffset = false;
@@ -534,7 +535,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber
pNode->EdgeColor.A = (byte)(edgeColor.W * 255);
if(!config.LightfinderLabelUseIcon)
if (!config.LightfinderLabelUseIcon)
{
pNode->AlignmentType = AlignmentType.Bottom;
}
@@ -642,10 +643,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber
{
return _mpNameplateAddon->NamePlateObjectArray[i];
}
else
{
return null;
}
return null;
}
private AtkComponentNode* GetNameplateComponentNode(int i)
@@ -653,12 +651,12 @@ public unsafe class NameplateHandler : IMediatorSubscriber
var nameplateObject = GetNameplateObject(i);
return nameplateObject != null ? nameplateObject.Value.RootComponentNode : null;
}
private HashSet<ulong> VisibleUserIds
=> [.. _pairUiService.GetSnapshot().PairsByUid.Values
.Where(u => u.IsVisible && u.PlayerCharacterId != uint.MaxValue)
.Select(u => (ulong)u.PlayerCharacterId)];
public void FlagRefresh()
{
_needsLabelRefresh = true;
@@ -680,7 +678,8 @@ public unsafe class NameplateHandler : IMediatorSubscriber
return;
_activeBroadcastingCids = newSet;
_logger.LogInformation("Active broadcast CIDs: {Cids}", string.Join(',', _activeBroadcastingCids));
if (_logger.IsEnabled(LogLevel.Information))
_logger.LogInformation("Active broadcast CIDs: {Cids}", string.Join(',', _activeBroadcastingCids));
FlagRefresh();
}