using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
-using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
using FFXIVClientStructs.FFXIV.Client.Game;
using LLib.GameData;
using Microsoft.Extensions.DependencyInjection;
internal static class Gather
{
- internal sealed class Factory(
- IServiceProvider serviceProvider,
- MovementController movementController,
- GatheringPointRegistry gatheringPointRegistry,
- IClientState clientState,
- GatheringData gatheringData,
- TerritoryData territoryData,
- ILogger<Factory> logger) : ITaskFactory
+ internal sealed class Factory : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
foreach (var itemToGather in step.ItemsToGather)
{
- EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
- if (!gatheringData.TryGetGatheringPointId(itemToGather.ItemId, currentClassJob,
- out GatheringPointId? gatheringPointId))
- throw new TaskException($"No gathering point found for item {itemToGather.ItemId}");
+ yield return new DelayedGatheringTask(itemToGather, quest);
+ }
+ }
+ }
- if (!gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? gatheringRoot))
- throw new TaskException($"No path found for gathering point {gatheringPointId}");
+ internal sealed record DelayedGatheringTask(GatheredItem GatheredItem, Quest Quest) : ITask
+ {
+ public override string ToString() => $"Gathering(pending for {GatheredItem.ItemId})";
+ }
- if (HasRequiredItems(itemToGather))
- continue;
+ internal sealed class DelayedGatheringExecutor(
+ MovementController movementController,
+ GatheringData gatheringData,
+ GatheringPointRegistry gatheringPointRegistry,
+ TerritoryData territoryData,
+ IClientState clientState,
+ IServiceProvider serviceProvider,
+ ILogger<DelayedGatheringExecutor> logger) : TaskExecutor<DelayedGatheringTask>, IExtraTaskCreator
+ {
+ protected override bool Start() => true;
+
+ public override ETaskResult Update() => ETaskResult.CreateNewTasks;
+
+ public IEnumerable<ITask> CreateExtraTasks()
+ {
+ EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
+ if (!gatheringData.TryGetGatheringPointId(Task.GatheredItem.ItemId, currentClassJob,
+ out GatheringPointId? gatheringPointId))
+ throw new TaskException($"No gathering point found for item {Task.GatheredItem.ItemId}");
- using (var _ = logger.BeginScope("Gathering(inner)"))
+ if (!gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? gatheringRoot))
+ throw new TaskException($"No path found for gathering point {gatheringPointId}");
+
+ if (HasRequiredItems(Task.GatheredItem))
+ yield break;
+
+ using (var _ = logger.BeginScope("Gathering(inner)"))
+ {
+ QuestSequence gatheringSequence = new QuestSequence
{
- QuestSequence gatheringSequence = new QuestSequence
- {
- Sequence = 0,
- Steps = gatheringRoot.Steps
- };
- foreach (var gatheringStep in gatheringSequence.Steps)
- {
- foreach (var task in serviceProvider.GetRequiredService<TaskCreator>()
- .CreateTasks(quest, gatheringSequence, gatheringStep))
- if (task is WaitAtEnd.NextStep)
- yield return new SkipMarker();
- else
- yield return task;
- }
+ Sequence = 0,
+ Steps = gatheringRoot.Steps
+ };
+ foreach (var gatheringStep in gatheringSequence.Steps)
+ {
+ foreach (var task in serviceProvider.GetRequiredService<TaskCreator>()
+ .CreateTasks(Task.Quest, gatheringSequence, gatheringStep))
+ if (task is WaitAtEnd.NextStep)
+ yield return new SkipMarker();
+ else
+ yield return task;
}
+ }
- ushort territoryId = gatheringRoot.Steps.Last().TerritoryId;
- yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
- $"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
+ ushort territoryId = gatheringRoot.Steps.Last().TerritoryId;
+ yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
+ $"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
- yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
- "Wait(navmesh ready)");
+ yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
+ "Wait(navmesh ready)");
- yield return new GatheringTask(gatheringPointId, itemToGather);
- yield return new WaitAtEnd.WaitDelay();
- }
+ yield return new GatheringTask(gatheringPointId, Task.GatheredItem);
+ yield return new WaitAtEnd.WaitDelay();
}
private unsafe bool HasRequiredItems(GatheredItem itemToGather)
.AddTaskFactoryAndExecutor<StepDisabled.SkipRemainingTasks, StepDisabled.Factory,
StepDisabled.SkipDisabledStepsExecutor>();
serviceCollection.AddTaskFactory<EquipRecommended.BeforeDutyOrInstance>();
- serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
serviceCollection.AddTaskExecutor<Gather.SkipMarker, Gather.DoSkip>();
serviceCollection
.AddTaskFactoryAndExecutor<AetheryteShortcut.Task, AetheryteShortcut.Factory,
.AddTaskExecutor<AetheryteShortcut.MoveAwayFromAetheryte, AetheryteShortcut.MoveAwayFromAetheryteExecutor>();
serviceCollection
.AddTaskFactoryAndExecutor<SkipCondition.SkipTask, SkipCondition.Factory, SkipCondition.CheckSkip>();
+ serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
+ serviceCollection.AddTaskExecutor<Gather.DelayedGatheringTask, Gather.DelayedGatheringExecutor>();
serviceCollection
.AddTaskFactoryAndExecutor<AethernetShortcut.Task, AethernetShortcut.Factory,
AethernetShortcut.UseAethernetShortcut>();