From 42c0379a930cca602c2ab848b5a722ab1843eeb9 Mon Sep 17 00:00:00 2001 From: amki Date: Fri, 17 Jan 2025 01:58:18 +0100 Subject: [PATCH] Stop using Hunt Helper to detect A ranks and do it ourselves (#38) * Use object table to look for marks ourself Submit found marks to turtle --- ScoutHelper/Managers/HuntHelperManager.cs | 28 +----- ScoutHelper/Managers/HuntMarkManager.cs | 117 ++++++++++++++++++++++ ScoutHelper/Managers/TurtleManager.cs | 46 ++++++++- ScoutHelper/Plugin.cs | 9 +- ScoutHelper/Windows/MainWindow.cs | 8 +- 5 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 ScoutHelper/Managers/HuntMarkManager.cs diff --git a/ScoutHelper/Managers/HuntHelperManager.cs b/ScoutHelper/Managers/HuntHelperManager.cs index a6c545b..d3d73af 100644 --- a/ScoutHelper/Managers/HuntHelperManager.cs +++ b/ScoutHelper/Managers/HuntHelperManager.cs @@ -1,4 +1,4 @@ -using CSharpFunctionalExtensions; +using CSharpFunctionalExtensions; using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc.Exceptions; using ScoutHelper.Models; @@ -44,7 +44,7 @@ TurtleManager turtleManager CheckVersion(); _cgEnable.Subscribe(OnEnable); _cgDisable.Subscribe(OnDisable); - _cgMarkSeen.Subscribe(OnMarkSeen); + //_cgMarkSeen.Subscribe(OnMarkSeen); } public void Dispose() { @@ -83,29 +83,7 @@ private void CheckVersion(uint? version = null) { } private void OnMarkSeen(TrainMob mark) { - if (!_turtleManager.IsTurtleCollabbing) return; - - _turtleManager.UpdateCurrentSession(mark.AsSingletonList()) - .ContinueWith( - task => { - switch (task.Result) { - case TurtleHttpStatus.Success: - _chat.TaggedPrint($"added {mark.Name} to the turtle session."); - break; - case TurtleHttpStatus.NoSupportedMobs: - _chat.TaggedPrint($"{mark.Name} was seen, but is not supported by turtle and will not be added to the session."); - break; - case TurtleHttpStatus.HttpError: - _chat.TaggedPrintError($"something went wrong when adding {mark.Name} to the turtle session ;-;."); - break; - } - }, - TaskContinuationOptions.OnlyOnRanToCompletion - ) - .ContinueWith( - task => _log.Error(task.Exception, "failed to update turtle session"), - TaskContinuationOptions.OnlyOnFaulted - ); + _turtleManager.OnMarkSeen(mark); } public Result, string> GetTrainList() { diff --git a/ScoutHelper/Managers/HuntMarkManager.cs b/ScoutHelper/Managers/HuntMarkManager.cs new file mode 100644 index 0000000..d16ab6f --- /dev/null +++ b/ScoutHelper/Managers/HuntMarkManager.cs @@ -0,0 +1,117 @@ +using CSharpFunctionalExtensions; +using System; +using System.Collections.Generic; +using Dalamud.Plugin; +using Dalamud.Plugin.Services; +using Dalamud.Game.ClientState.Objects.Types; +using XIVHuntUtils.Models; +using System.Linq; +using System.Numerics; +using FFXIVClientStructs.FFXIV.Client.Game.UI; +using static XIVHuntUtils.Utils.XivUtils; +using Lumina.Excel.Sheets; + +namespace ScoutHelper.Managers; + +using MobDict = IDictionary; + +public class HuntMarkManager : IDisposable { + private static readonly TimeSpan ExecDelay = TimeSpan.FromSeconds(1); + + private readonly IFramework _framework; + private readonly IObjectTable _objectTable; + private readonly IClientState _clientState; + private readonly IPluginLog _log; + private readonly IChatGui _chat; + + private TimeSpan _lastUpdate = TimeSpan.FromSeconds(0); + + private List _ARankbNPCIds = new(); + private List _sentARankIds = new(); + + public event Action? OnMarkFound; + + public HuntMarkManager( + IFramework framework, + IPluginLog log, + IChatGui chat, + IClientState clientState, + IObjectTable objectTable + ) { + _framework = framework; + _log = log; + _chat = chat; + _clientState = clientState; + _objectTable = objectTable; + } + + private bool IsHWTerritory(uint territoryId) { + //EVERYTHING EXCEPT HEAVENSWARD HAS A SCALE OF 100, BUT FOR SOME REASON HW HAS 95 + if (territoryId is >= 397 and <= 402) return true; + return false; + } + + private unsafe uint GetCurrentInstance() { + return UIState.Instance()->PublicInstance.InstanceId; + } + + private void CheckObjectTable() { + foreach (var obj in _objectTable) { + if (obj is not IBattleNpc mob) continue; + var battlenpc = mob as IBattleNpc; + + if (_ARankbNPCIds.Contains(battlenpc.NameId)) { + if (_sentARankIds.Contains(battlenpc.NameId)) { + //_log.Debug($"Got that A already..."); + continue; + } + var trainMob = new ScoutHelper.Models.TrainMob(); + + trainMob.Name = battlenpc.Name.ToString(); + trainMob.MobId = battlenpc.NameId; + trainMob.TerritoryId = _clientState.TerritoryType; + //trainMob.MapId = + trainMob.Instance = GetCurrentInstance(); + trainMob.Position = XIVHuntUtils.Utils.XivUtils.AsMapPosition( + new Vector2(battlenpc.Position.X, battlenpc.Position.Z), + IsHWTerritory(trainMob.TerritoryId) + ); + trainMob.Dead = battlenpc.IsDead; + //trainMob.LastSeenUtc = + _log.Debug( + $"I spy with my little eye: {trainMob.Name} ({trainMob.MobId}) in {trainMob.TerritoryId} i{trainMob.Instance} @{trainMob.Position} Dead?{trainMob.Dead}" + ); + OnMarkFound?.Invoke(trainMob); + _sentARankIds.Add(trainMob.MobId); + } + } + } + + private void Tick(IFramework framework) { + _lastUpdate += framework.UpdateDelta; + if (_lastUpdate > ExecDelay) { + DoUpdate(framework); + _lastUpdate = new(0); + } + } + + private void DoUpdate(IFramework framework) { + CheckObjectTable(); + } + + public void StartLooking(MobDict mobIdToTurtleId) { + _log.Debug("HuntMarkManager: Start looking for Ranks"); + _ARankbNPCIds = mobIdToTurtleId.Keys.ToList(); + _sentARankIds = new(); + _framework.Update += Tick; + } + + public void StopLooking() { + _log.Debug("HuntMarkManager: Stop looking for Ranks"); + _framework.Update -= Tick; + } + + public void Dispose() { + _framework.Update -= Tick; + } +} diff --git a/ScoutHelper/Managers/TurtleManager.cs b/ScoutHelper/Managers/TurtleManager.cs index 539d4ff..6565a72 100644 --- a/ScoutHelper/Managers/TurtleManager.cs +++ b/ScoutHelper/Managers/TurtleManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -31,8 +31,10 @@ public partial class TurtleManager : IDisposable { private static partial Regex CollabLinkRegex(); private readonly IPluginLog _log; + private readonly IChatGui _chat; private readonly Configuration _conf; private readonly IClientState _clientState; + private readonly HuntMarkManager _huntMarkManager; private readonly HttpClientGenerator _httpClientGenerator; private MobDict MobIdToTurtleId { get; } @@ -45,15 +47,19 @@ public partial class TurtleManager : IDisposable { public TurtleManager( IPluginLog log, + IChatGui chat, Configuration conf, IClientState clientState, ScoutHelperOptions options, TerritoryManager territoryManager, + HuntMarkManager huntMarkManager, MobManager mobManager ) { _log = log; + _chat = chat; _conf = conf; _clientState = clientState; + _huntMarkManager = huntMarkManager; _httpClientGenerator = new HttpClientGenerator( _log, @@ -63,10 +69,13 @@ MobManager mobManager (MobIdToTurtleId, TerritoryIdToTurtleData) = LoadData(options.TurtleDataFile, territoryManager, mobManager); + _huntMarkManager.OnMarkFound += OnMarkSeen; } public void Dispose() { _httpClientGenerator.Dispose(); + _huntMarkManager.StopLooking(); + _huntMarkManager.OnMarkFound -= OnMarkSeen; GC.SuppressFinalize(this); } @@ -78,16 +87,49 @@ public void Dispose() { _currentCollabSession = match.Groups["session"].Value; _currentCollabPassword = match.Groups["password"].Value; IsTurtleCollabbing = true; + _huntMarkManager.StartLooking(MobIdToTurtleId); return (_currentCollabSession, _currentCollabPassword); } + public void OnMarkSeen(TrainMob mark) { + if (!IsTurtleCollabbing) return; + + UpdateCurrentSession(mark.AsSingletonList()) + .ContinueWith( + task => { + switch (task.Result) { + case TurtleHttpStatus.Success: + _chat.TaggedPrint($"added {mark.Name} to the turtle session."); + break; + case TurtleHttpStatus.NoSupportedMobs: + _chat.TaggedPrint( + $"{mark.Name} was seen, but is not supported by turtle and will not be added to the session." + ); + break; + case TurtleHttpStatus.HttpError: + _chat.TaggedPrintError($"something went wrong when adding {mark.Name} to the turtle session ;-;."); + break; + } + }, + TaskContinuationOptions.OnlyOnRanToCompletion + ) + .ContinueWith( + task => _log.Error(task.Exception, "failed to update turtle session"), + TaskContinuationOptions.OnlyOnFaulted + ); + } + public void RejoinLastCollabSession() { if (_currentCollabSession.IsNullOrEmpty() || _currentCollabPassword.IsNullOrEmpty()) throw new Exception("cannot rejoin the last turtle collab session as there is no last session."); IsTurtleCollabbing = true; + _huntMarkManager.StartLooking(MobIdToTurtleId); } - public void LeaveCollabSession() => IsTurtleCollabbing = false; + public void LeaveCollabSession() { + IsTurtleCollabbing = false; + _huntMarkManager.StopLooking(); + } public async Task UpdateCurrentSession(IList train) { var turtleSupportedMobs = train.Where(mob => MobIdToTurtleId.ContainsKey(mob.MobId)).AsList(); diff --git a/ScoutHelper/Plugin.cs b/ScoutHelper/Plugin.cs index 09fb274..3cd6335 100644 --- a/ScoutHelper/Plugin.cs +++ b/ScoutHelper/Plugin.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using Dalamud.Game.Command; @@ -29,12 +29,14 @@ public sealed class Plugin : IDalamudPlugin { private readonly Action _dispose; public Plugin( + IFramework framework, IDalamudPluginInterface pluginInterface, IPluginLog log, IChatGui chatGui, ICommandManager commandManager, IClientState clientState, - IDataManager dataManager + IDataManager dataManager, + IObjectTable objectTable ) { _log = log; @@ -42,12 +44,14 @@ IDataManager dataManager conf.Initialize(_log, pluginInterface); var serviceProvider = new ServiceCollection() + .AddSingleton(framework) .AddSingleton(pluginInterface) .AddSingleton(_log) .AddSingleton(chatGui) .AddSingleton(commandManager) .AddSingleton(clientState) .AddSingleton(dataManager) + .AddSingleton(objectTable) .AddSingleton(conf) .AddSingleton( new ScoutHelperOptions( @@ -59,6 +63,7 @@ IDataManager dataManager .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/ScoutHelper/Windows/MainWindow.cs b/ScoutHelper/Windows/MainWindow.cs index 698dc82..b3b77f8 100644 --- a/ScoutHelper/Windows/MainWindow.cs +++ b/ScoutHelper/Windows/MainWindow.cs @@ -392,11 +392,13 @@ private void DrawTurtleCollabPopup() { ImGui.PushTextWrapPos(contentWidth); ImGuiPlus.Heading("SESSION", centered: true); - + ImGui.Checkbox("include name", ref _conf.IncludeNameInTurtleSession); ImGui.SameLine(); - ImGuiComponents.HelpMarker("share your character name in the turtle session, so others can see that you contributed."); - + ImGuiComponents.HelpMarker( + "share your character name in the turtle session, so others can see that you contributed." + ); + ImGui.BeginDisabled(!_turtleManager.IsTurtleCollabbing); if (ImGui.Button("LEAVE SESSION")) _turtleManager.LeaveCollabSession(); ImGui.EndDisabled();