qstcompanion v1.0.1
This commit is contained in:
parent
3e10cbbbf2
commit
44c67ab71b
79 changed files with 21148 additions and 0 deletions
|
|
@ -0,0 +1,256 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
|
||||
namespace QuestionableCompanion.Services;
|
||||
|
||||
public class QuestDetectionService : IDisposable
|
||||
{
|
||||
private readonly IFramework framework;
|
||||
|
||||
private readonly IPluginLog log;
|
||||
|
||||
private readonly IClientState clientState;
|
||||
|
||||
private readonly HashSet<uint> acceptedQuests = new HashSet<uint>();
|
||||
|
||||
private readonly HashSet<uint> completedQuests = new HashSet<uint>();
|
||||
|
||||
private HashSet<uint> completedQuestCache = new HashSet<uint>();
|
||||
|
||||
private DateTime lastCacheRefresh = DateTime.MinValue;
|
||||
|
||||
private const int CACHE_REFRESH_MINUTES = 5;
|
||||
|
||||
public event Action<uint, string>? QuestAccepted;
|
||||
|
||||
public event Action<uint, string>? QuestCompleted;
|
||||
|
||||
public QuestDetectionService(IFramework framework, IPluginLog log, IClientState clientState)
|
||||
{
|
||||
this.framework = framework;
|
||||
this.log = log;
|
||||
this.clientState = clientState;
|
||||
framework.Update += OnFrameworkUpdate;
|
||||
log.Information("[QuestDetection] Service initialized");
|
||||
}
|
||||
|
||||
private void OnFrameworkUpdate(IFramework framework)
|
||||
{
|
||||
if (!clientState.IsLoggedIn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
CheckQuestUpdates();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Debug("[QuestDetection] Error in framework update: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void CheckQuestUpdates()
|
||||
{
|
||||
QuestManager* questManager = QuestManager.Instance();
|
||||
if (questManager == null)
|
||||
{
|
||||
log.Debug("[QuestDetection] QuestManager instance is null");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Span<QuestWork> normalQuests = questManager->NormalQuests;
|
||||
if (normalQuests.Length == 0)
|
||||
{
|
||||
log.Debug("[QuestDetection] NormalQuests array is empty");
|
||||
return;
|
||||
}
|
||||
int maxSlots = Math.Min(normalQuests.Length, 30);
|
||||
for (int i = 0; i < maxSlots; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
QuestWork quest = normalQuests[i];
|
||||
if (quest.QuestId == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uint questId = quest.QuestId;
|
||||
if (!acceptedQuests.Contains(questId))
|
||||
{
|
||||
if (!IsQuestComplete(questId))
|
||||
{
|
||||
acceptedQuests.Add(questId);
|
||||
string questName = GetQuestName(questId);
|
||||
log.Information($"[QuestDetection] Quest Accepted: {questId} - {questName}");
|
||||
this.QuestAccepted?.Invoke(questId, questName);
|
||||
}
|
||||
}
|
||||
else if (!completedQuests.Contains(questId) && IsQuestComplete(questId))
|
||||
{
|
||||
completedQuests.Add(questId);
|
||||
string questName2 = GetQuestName(questId);
|
||||
log.Information($"[QuestDetection] Quest Completed: {questId} - {questName2}");
|
||||
this.QuestCompleted?.Invoke(questId, questName2);
|
||||
}
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
log.Debug($"[QuestDetection] Index {i} out of range, stopping quest check");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
log.Debug($"[QuestDetection] Error checking quest slot {i}: {ex2.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex3)
|
||||
{
|
||||
log.Warning("[QuestDetection] Error accessing quest data: " + ex3.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsQuestComplete(uint questId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return QuestManager.IsQuestComplete(questId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe bool IsQuestCompletedDirect(uint questId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (QuestManager.Instance() == null)
|
||||
{
|
||||
log.Warning("[QuestDetection] QuestManager instance not available");
|
||||
return false;
|
||||
}
|
||||
bool isComplete = QuestManager.IsQuestComplete(questId);
|
||||
log.Debug($"[QuestDetection] Quest {questId} completion status: {isComplete}");
|
||||
return isComplete;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"[QuestDetection] Failed to check quest {questId}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe List<uint> GetAllCompletedQuestIds()
|
||||
{
|
||||
List<uint> completed = new List<uint>();
|
||||
try
|
||||
{
|
||||
if (QuestManager.Instance() == null)
|
||||
{
|
||||
log.Warning("[QuestDetection] QuestManager instance not available");
|
||||
return completed;
|
||||
}
|
||||
log.Information("[QuestDetection] Scanning for completed quests...");
|
||||
foreach (var item in new List<(uint, uint)>
|
||||
{
|
||||
(1u, 3000u),
|
||||
(65000u, 71000u)
|
||||
})
|
||||
{
|
||||
uint start = item.Item1;
|
||||
uint end = item.Item2;
|
||||
for (uint i = start; i <= end; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (QuestManager.IsQuestComplete(i))
|
||||
{
|
||||
completed.Add(i);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Information($"[QuestDetection] Retrieved {completed.Count} completed quests");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[QuestDetection] Error while fetching completed quests: " + ex.Message);
|
||||
}
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void RefreshQuestCache()
|
||||
{
|
||||
try
|
||||
{
|
||||
log.Information("[QuestDetection] Refreshing quest cache...");
|
||||
List<uint> allCompleted = GetAllCompletedQuestIds();
|
||||
completedQuestCache = new HashSet<uint>(allCompleted);
|
||||
lastCacheRefresh = DateTime.Now;
|
||||
log.Information($"[QuestDetection] Quest cache refreshed with {completedQuestCache.Count} completed quests");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[QuestDetection] Failed to refresh quest cache: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsQuestCompletedCached(uint questId)
|
||||
{
|
||||
if (completedQuestCache.Count == 0 || (DateTime.Now - lastCacheRefresh).TotalMinutes > 5.0)
|
||||
{
|
||||
RefreshQuestCache();
|
||||
}
|
||||
return completedQuestCache.Contains(questId);
|
||||
}
|
||||
|
||||
private string GetQuestName(uint questId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $"Quest {questId}";
|
||||
}
|
||||
catch
|
||||
{
|
||||
return $"Quest {questId}";
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetTracking()
|
||||
{
|
||||
acceptedQuests.Clear();
|
||||
completedQuests.Clear();
|
||||
completedQuestCache.Clear();
|
||||
lastCacheRefresh = DateTime.MinValue;
|
||||
log.Information("[QuestDetection] Tracking reset");
|
||||
}
|
||||
|
||||
public bool IsQuestAccepted(uint questId)
|
||||
{
|
||||
return acceptedQuests.Contains(questId);
|
||||
}
|
||||
|
||||
public bool IsQuestCompleted(uint questId)
|
||||
{
|
||||
return completedQuests.Contains(questId);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
framework.Update -= OnFrameworkUpdate;
|
||||
acceptedQuests.Clear();
|
||||
completedQuests.Clear();
|
||||
completedQuestCache.Clear();
|
||||
log.Information("[QuestDetection] Service disposed");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue