71 lines
2.2 KiB
C#
71 lines
2.2 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Dalamud.Plugin.Services;
|
|
using LLib.Shop;
|
|
using Lumina.Excel;
|
|
using Lumina.Excel.Sheets;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Questionable.Data;
|
|
|
|
internal sealed class MenderDataService(IDataManager dataManager, NpcPositionCache npcPositionCache, ILogger<MenderDataService> logger)
|
|
{
|
|
public static readonly IReadOnlyList<MenderNpc> CityFallbacks = new global::_003C_003Ez__ReadOnlyArray<MenderNpc>(new MenderNpc[3]
|
|
{
|
|
new MenderNpc(1003251u, 128, new Vector3(17.715698f, 40.200005f, 3.9520264f)),
|
|
new MenderNpc(1000394u, 132, new Vector3(24.826416f, -8f, 93.18677f)),
|
|
new MenderNpc(1004416u, 130, new Vector3(32.85266f, 6.999999f, -81.31531f))
|
|
});
|
|
|
|
private readonly object _lock = new object();
|
|
|
|
private ILookup<ushort, MenderNpc>? _byTerritory;
|
|
|
|
public MenderNpc? FindNearestInTerritory(ushort territoryId, Vector3 nearPosition)
|
|
{
|
|
ILookup<ushort, MenderNpc> lookup;
|
|
lock (_lock)
|
|
{
|
|
if (_byTerritory == null && !npcPositionCache.IsBuilt)
|
|
{
|
|
return null;
|
|
}
|
|
lookup = _byTerritory ?? (_byTerritory = BuildIndex());
|
|
}
|
|
return lookup[territoryId].OrderBy((MenderNpc x) => Vector3.DistanceSquared(x.Position, nearPosition)).FirstOrDefault();
|
|
}
|
|
|
|
private ILookup<ushort, MenderNpc> BuildIndex()
|
|
{
|
|
ExcelSheet<ENpcBase> excelSheet = dataManager.GetExcelSheet<ENpcBase>();
|
|
List<MenderNpc> list = new List<MenderNpc>();
|
|
foreach (uint allNpcId in npcPositionCache.GetAllNpcIds())
|
|
{
|
|
if (!excelSheet.TryGetRow(allNpcId, out var row))
|
|
{
|
|
continue;
|
|
}
|
|
bool flag = false;
|
|
for (int i = 0; i < row.ENpcData.Count; i++)
|
|
{
|
|
if (row.ENpcData[i].RowId == 720915)
|
|
{
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (flag)
|
|
{
|
|
(ushort, Vector3)? position = npcPositionCache.GetPosition(allNpcId);
|
|
if (position.HasValue)
|
|
{
|
|
(ushort, Vector3) valueOrDefault = position.GetValueOrDefault();
|
|
list.Add(new MenderNpc(allNpcId, valueOrDefault.Item1, valueOrDefault.Item2));
|
|
}
|
|
}
|
|
}
|
|
logger.LogDebug("Mender index built with {Count} menders across {Territories} territories", list.Count, list.Select((MenderNpc x) => x.TerritoryId).Distinct().Count());
|
|
return list.ToLookup((MenderNpc x) => x.TerritoryId);
|
|
}
|
|
}
|