forked from liza/Deliveroo
Try to fix a potential issue around list not refreshing/turning in ghost items
This commit is contained in:
parent
66b248cac3
commit
74aaf1365e
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
<TargetFramework>net7.0-windows</TargetFramework>
|
||||||
<Version>2.5</Version>
|
<Version>2.6</Version>
|
||||||
<LangVersion>11.0</LangVersion>
|
<LangVersion>11.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
@ -166,13 +166,16 @@ partial class DeliverooPlugin
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const int UnitListCount = 18;
|
||||||
private unsafe AtkUnitBase* GetAddonById(uint id)
|
private unsafe AtkUnitBase* GetAddonById(uint id)
|
||||||
{
|
{
|
||||||
var unitManagers = &AtkStage.GetSingleton()->RaptureAtkUnitManager->AtkUnitManager.DepthLayerOneList;
|
var unitManagers = &AtkStage.GetSingleton()->RaptureAtkUnitManager->AtkUnitManager.DepthLayerOneList;
|
||||||
for (var i = 0; i < 18; i++)
|
for (var i = 0; i < UnitListCount; i++)
|
||||||
{
|
{
|
||||||
foreach (AtkUnitBase* unitBase in unitManagers[i].EntriesSpan)
|
var unitManager = &unitManagers[i];
|
||||||
|
foreach (var j in Enumerable.Range(0, Math.Min(unitManager->Count, unitManager->EntriesSpan.Length)))
|
||||||
{
|
{
|
||||||
|
var unitBase = unitManager->EntriesSpan[j].Value;
|
||||||
if (unitBase != null && unitBase->ID == id)
|
if (unitBase != null && unitBase->ID == id)
|
||||||
{
|
{
|
||||||
return unitBase;
|
return unitBase;
|
||||||
@ -203,4 +206,11 @@ partial class DeliverooPlugin
|
|||||||
{
|
{
|
||||||
return addon->IsVisible && addon->UldManager.LoadedState == AtkLoadState.Loaded;
|
return addon->IsVisible && addon->UldManager.LoadedState == AtkLoadState.Loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe string? ReadAtkString(AtkValue atkValue)
|
||||||
|
{
|
||||||
|
if (atkValue.String != null)
|
||||||
|
return MemoryHelper.ReadSeStringNullTerminated(new nint(atkValue.String)).ToString();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ partial class DeliverooPlugin
|
|||||||
|
|
||||||
private void OpenGcSupplyFollowUp()
|
private void OpenGcSupplyFollowUp()
|
||||||
{
|
{
|
||||||
|
ResetTurnInErrorHandling();
|
||||||
CurrentStage = Stage.SelectExpertDeliveryTab;
|
CurrentStage = Stage.SelectExpertDeliveryTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
|
using Dalamud.Memory;
|
||||||
using Deliveroo.GameData;
|
using Deliveroo.GameData;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
@ -38,6 +39,7 @@ partial class DeliverooPlugin
|
|||||||
if (addonGc->SelectedTab == 2)
|
if (addonGc->SelectedTab == 2)
|
||||||
{
|
{
|
||||||
_pluginLog.Information("Tab already selected, probably due to haseltweaks");
|
_pluginLog.Information("Tab already selected, probably due to haseltweaks");
|
||||||
|
ResetTurnInErrorHandling();
|
||||||
CurrentStage = Stage.SelectItemToTurnIn;
|
CurrentStage = Stage.SelectItemToTurnIn;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -50,11 +52,18 @@ partial class DeliverooPlugin
|
|||||||
new() { Type = 0, Int = 0 }
|
new() { Type = 0, Int = 0 }
|
||||||
};
|
};
|
||||||
addon->FireCallback(3, selectExpertDeliveryTab);
|
addon->FireCallback(3, selectExpertDeliveryTab);
|
||||||
_lastTurnInListLength = int.MaxValue;
|
ResetTurnInErrorHandling();
|
||||||
CurrentStage = Stage.SelectItemToTurnIn;
|
CurrentStage = Stage.SelectItemToTurnIn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ResetTurnInErrorHandling(int listSize = int.MaxValue)
|
||||||
|
{
|
||||||
|
_pluginLog.Verbose("Resetting error handling state");
|
||||||
|
_lastTurnInListSize = listSize;
|
||||||
|
_turnInErrors = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe void SelectItemToTurnIn()
|
private unsafe void SelectItemToTurnIn()
|
||||||
{
|
{
|
||||||
var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply);
|
var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply);
|
||||||
@ -86,13 +95,35 @@ partial class DeliverooPlugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addonGc->ListEmptyTextNode->AtkResNode.IsVisible)
|
int currentListSize = addonGc->ExpertDeliveryList->ListLength;
|
||||||
|
if (addonGc->ListEmptyTextNode->AtkResNode.IsVisible || currentListSize == 0)
|
||||||
{
|
{
|
||||||
|
_pluginLog.Information($"No items to turn in {addonGc->ListEmptyTextNode->AtkResNode.IsVisible}, {currentListSize})");
|
||||||
CurrentStage = Stage.CloseGcSupplyThenStop;
|
CurrentStage = Stage.CloseGcSupplyThenStop;
|
||||||
addon->FireCallbackInt(-1);
|
addon->FireCallbackInt(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback: Two successive calls to SelectItemToTurnIn should *not* have lists of the same length, or
|
||||||
|
// something is wrong.
|
||||||
|
if (_turnInErrors > 10)
|
||||||
|
{
|
||||||
|
_turnInWindow.Error = "Unable to refresh item list";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentListSize >= _lastTurnInListSize)
|
||||||
|
{
|
||||||
|
_turnInErrors++;
|
||||||
|
_pluginLog.Information($"Trying to refresh expert delivery list manually ({_turnInErrors}, old list size = {_lastTurnInListSize}, new list size = {currentListSize})...");
|
||||||
|
addon->FireCallbackInt(2);
|
||||||
|
|
||||||
|
_continueAt = DateTime.Now.AddSeconds(0.1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetTurnInErrorHandling(currentListSize);
|
||||||
|
|
||||||
var agent = (AgentGrandCompanySupply*)agentInterface;
|
var agent = (AgentGrandCompanySupply*)agentInterface;
|
||||||
List<TurnInItem> items = BuildTurnInList(agent);
|
List<TurnInItem> items = BuildTurnInList(agent);
|
||||||
if (items.Count == 0)
|
if (items.Count == 0)
|
||||||
@ -103,19 +134,6 @@ partial class DeliverooPlugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: Two successive calls to SelectItemToTurnIn should *not* have lists of the same length, or
|
|
||||||
// something is wrong.
|
|
||||||
if (items.Count >= _lastTurnInListLength)
|
|
||||||
{
|
|
||||||
_pluginLog.Warning("Closing GC supply window, possible invalid loop detected");
|
|
||||||
|
|
||||||
CurrentStage = Stage.CloseGcSupply;
|
|
||||||
addon->FireCallbackInt(-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastTurnInListLength = items.Count;
|
|
||||||
|
|
||||||
// TODO The way the items are handled above, we don't actually know if items[0] is the first visible item
|
// TODO The way the items are handled above, we don't actually know if items[0] is the first visible item
|
||||||
// in the list, it is "only" the highest-value item to turn in.
|
// in the list, it is "only" the highest-value item to turn in.
|
||||||
//
|
//
|
||||||
@ -158,39 +176,15 @@ partial class DeliverooPlugin
|
|||||||
if (TryGetAddonByName<AddonGrandCompanySupplyReward>("GrandCompanySupplyReward",
|
if (TryGetAddonByName<AddonGrandCompanySupplyReward>("GrandCompanySupplyReward",
|
||||||
out var addonSupplyReward) && IsAddonReady(&addonSupplyReward->AtkUnitBase))
|
out var addonSupplyReward) && IsAddonReady(&addonSupplyReward->AtkUnitBase))
|
||||||
{
|
{
|
||||||
|
_pluginLog.Information($"Turning in '{ReadAtkString(addonSupplyReward->AtkUnitBase.AtkValues[4])}'");
|
||||||
|
|
||||||
addonSupplyReward->AtkUnitBase.FireCallbackInt(0);
|
addonSupplyReward->AtkUnitBase.FireCallbackInt(0);
|
||||||
_continueAt = DateTime.Now.AddSeconds(0.58);
|
_continueAt = DateTime.Now.AddSeconds(0.58);
|
||||||
CurrentStage = Stage.FinalizeTurnIn1;
|
CurrentStage = Stage.FinalizeTurnIn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void FinalizeTurnInItem1()
|
private unsafe void FinalizeTurnInItem()
|
||||||
{
|
|
||||||
if (TryGetAddonByName<AddonGrandCompanySupplyList>("GrandCompanySupplyList",
|
|
||||||
out var addonSupplyList) && IsAddonReady(&addonSupplyList->AtkUnitBase))
|
|
||||||
{
|
|
||||||
addonSupplyList->AtkUnitBase.FireCallbackInt(2);
|
|
||||||
CurrentStage = Stage.FinalizeTurnIn2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe void FinalizeTurnInItem2()
|
|
||||||
{
|
|
||||||
if (TryGetAddonByName<AddonGrandCompanySupplyList>("GrandCompanySupplyList",
|
|
||||||
out var addonSupplyList) && IsAddonReady(&addonSupplyList->AtkUnitBase))
|
|
||||||
{
|
|
||||||
var updateUnknown = stackalloc AtkValue[]
|
|
||||||
{
|
|
||||||
new() { Type = ValueType.Int, Int = 4 },
|
|
||||||
new() { Type = ValueType.Int, Int = 0 },
|
|
||||||
new() { Type = 0, Int = 0 }
|
|
||||||
};
|
|
||||||
addonSupplyList->AtkUnitBase.FireCallback(3, updateUnknown);
|
|
||||||
CurrentStage = Stage.FinalizeTurnIn3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe void FinalizeTurnInItem3()
|
|
||||||
{
|
{
|
||||||
if (TryGetAddonByName<AddonGrandCompanySupplyList>("GrandCompanySupplyList",
|
if (TryGetAddonByName<AddonGrandCompanySupplyList>("GrandCompanySupplyList",
|
||||||
out var addonSupplyList) && IsAddonReady(&addonSupplyList->AtkUnitBase))
|
out var addonSupplyList) && IsAddonReady(&addonSupplyList->AtkUnitBase))
|
||||||
|
@ -49,7 +49,8 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
|
|||||||
|
|
||||||
private Stage _currentStageInternal = Stage.Stopped;
|
private Stage _currentStageInternal = Stage.Stopped;
|
||||||
private DateTime _continueAt = DateTime.MinValue;
|
private DateTime _continueAt = DateTime.MinValue;
|
||||||
private int _lastTurnInListLength = int.MaxValue;
|
private int _lastTurnInListSize = int.MaxValue;
|
||||||
|
private uint _turnInErrors = 0;
|
||||||
private List<PurchaseItemRequest> _itemsToPurchaseNow = new();
|
private List<PurchaseItemRequest> _itemsToPurchaseNow = new();
|
||||||
|
|
||||||
public DeliverooPlugin(DalamudPluginInterface pluginInterface, IChatGui chatGui, IGameGui gameGui,
|
public DeliverooPlugin(DalamudPluginInterface pluginInterface, IChatGui chatGui, IGameGui gameGui,
|
||||||
@ -240,16 +241,8 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
|
|||||||
TurnInSelectedItem();
|
TurnInSelectedItem();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Stage.FinalizeTurnIn1:
|
case Stage.FinalizeTurnIn:
|
||||||
FinalizeTurnInItem1();
|
FinalizeTurnInItem();
|
||||||
break;
|
|
||||||
|
|
||||||
case Stage.FinalizeTurnIn2:
|
|
||||||
FinalizeTurnInItem2();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Stage.FinalizeTurnIn3:
|
|
||||||
FinalizeTurnInItem3();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Stage.CloseGcSupply:
|
case Stage.CloseGcSupply:
|
||||||
|
@ -7,9 +7,7 @@ internal enum Stage
|
|||||||
SelectExpertDeliveryTab,
|
SelectExpertDeliveryTab,
|
||||||
SelectItemToTurnIn,
|
SelectItemToTurnIn,
|
||||||
TurnInSelected,
|
TurnInSelected,
|
||||||
FinalizeTurnIn1,
|
FinalizeTurnIn,
|
||||||
FinalizeTurnIn2,
|
|
||||||
FinalizeTurnIn3,
|
|
||||||
CloseGcSupply,
|
CloseGcSupply,
|
||||||
CloseGcSupplyThenStop,
|
CloseGcSupplyThenStop,
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user