using System; using System.Threading; using Dalamud.Plugin; using Dalamud.Plugin.Services; using LLib.Shop; using Microsoft.Extensions.Logging; using SmartNav; using SmartNav.Data; namespace Questionable.Data; internal sealed class NpcPositionCacheWarmer : IDisposable { private readonly CancellationTokenSource _cts = new CancellationTokenSource(); private readonly Thread? _thread; public NpcPositionCacheWarmer(NpcPositionCache npcPositionCache, WarpDataService warpDataService, NavRouter navRouter, LgbWorkerSupervisor workerSupervisor, IDalamudPluginInterface pluginInterface, IDataManager dataManager, NpcPositionCacheOptions cacheOptions, ILogger logger) { NpcPositionCacheWarmer npcPositionCacheWarmer = this; if (npcPositionCache.IsBuilt) { return; } _thread = new Thread((ThreadStart)delegate { try { bool flag = false; string fullName = dataManager.GameData.DataPath.FullName; string gameVersion = cacheOptions.GameVersion; string cacheDirectory = cacheOptions.CacheDirectory; string directoryName = pluginInterface.AssemblyLocation.DirectoryName; if (fullName != null && gameVersion != null && cacheDirectory != null && directoryName != null) { flag = workerSupervisor.RunWorker(fullName, gameVersion, cacheDirectory, directoryName, npcPositionCacheWarmer._cts.Token); if (flag) { npcPositionCache.TryLoadFromDisk(); } } if (!flag) { logger.LogInformation("Falling back to in-process LGB scan"); npcPositionCache.WarmUp(npcPositionCacheWarmer._cts.Token); } if (warpDataService.ApplyDerivedSources()) { navRouter.InvalidateStaticGraph(); logger.LogInformation("Applied derived warp sources after NPC position warm-up"); } } catch (OperationCanceledException) { } catch (Exception exception) { logger.LogError(exception, "NPC position cache warm-up failed"); } }) { IsBackground = true, Priority = ThreadPriority.BelowNormal, Name = "Questionable.NpcPositionCacheWarmer" }; _thread.Start(); } public void Dispose() { _cts.Cancel(); _thread?.Join(TimeSpan.FromSeconds(1L)); _cts.Dispose(); } }