This commit is contained in:
Liza 2024-03-27 08:26:14 +01:00
parent ec256ac090
commit 238b58d555
Signed by: liza
GPG Key ID: 7199F8D727D55F67
10 changed files with 1138 additions and 89 deletions

1017
ARControl/.editorconfig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<Version>3.3</Version> <Version>4.0</Version>
<LangVersion>11.0</LangVersion> <LangVersion>12</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>

View File

@ -44,6 +44,9 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
IClientState clientState, IChatGui chatGui, ICommandManager commandManager, ITextureProvider textureProvider, IClientState clientState, IChatGui chatGui, ICommandManager commandManager, ITextureProvider textureProvider,
IPluginLog pluginLog) IPluginLog pluginLog)
{ {
ArgumentNullException.ThrowIfNull(pluginInterface);
ArgumentNullException.ThrowIfNull(dataManager);
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_clientState = clientState; _clientState = clientState;
_chatGui = chatGui; _chatGui = chatGui;
@ -226,28 +229,7 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
} }
else else
{ {
_chatGui.Print( PrintNextVentureMessage(retainerName, venture, reward, list);
new SeString(new UIForegroundPayload(579))
.Append(SeIconChar.Collectible.ToIconString())
.Append(new UIForegroundPayload(0))
.Append($" Sending retainer ")
.Append(new UIForegroundPayload(1))
.Append(retainerName)
.Append(new UIForegroundPayload(0))
.Append(" to collect ")
.Append(new UIForegroundPayload(1))
.Append($"{reward.Quantity}x ")
.Append(new ItemPayload(venture.ItemId))
.Append(venture.Name)
.Append(RawPayload.LinkTerminator)
.Append(new UIForegroundPayload(0))
.Append(" for ")
.Append(new UIForegroundPayload(1))
.Append($"{list.Name} {list.GetIcon()}")
.Append(new UIForegroundPayload(0))
.Append("."));
_pluginLog.Information(
$"Setting AR to use venture {venture.RowId}, which should retrieve {reward.Quantity}x {venture.Name}");
if (!dryRun) if (!dryRun)
{ {
@ -272,21 +254,7 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
// fallback: managed but no venture found/ // fallback: managed but no venture found/
if (retainer.LastVenture != QuickVentureId) if (retainer.LastVenture != QuickVentureId)
{ {
_chatGui.Print( PrintEndOfListMessage(retainerName, retainer);
new SeString(new UIForegroundPayload(579))
.Append(SeIconChar.Collectible.ToIconString())
.Append(new UIForegroundPayload(0))
.Append($" No tasks left for retainer ")
.Append(new UIForegroundPayload(1))
.Append(retainerName)
.Append(new UIForegroundPayload(0))
.Append(", sending to ")
.Append(new UIForegroundPayload(1))
.Append("Quick Venture")
.Append(new UIForegroundPayload(0))
.Append("."));
_pluginLog.Information($"No tasks left (previous venture = {retainer.LastVenture}), using QV");
if (!dryRun) if (!dryRun)
{ {
retainer.HasVenture = true; retainer.HasVenture = true;
@ -310,6 +278,50 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
} }
} }
private void PrintNextVentureMessage(string retainerName, Venture venture, VentureReward reward, Configuration.ItemList list)
{
_chatGui.Print(
new SeString(new UIForegroundPayload(579))
.Append(SeIconChar.Collectible.ToIconString())
.Append(new UIForegroundPayload(0))
.Append($" Sending retainer ")
.Append(new UIForegroundPayload(1))
.Append(retainerName)
.Append(new UIForegroundPayload(0))
.Append(" to collect ")
.Append(new UIForegroundPayload(1))
.Append($"{reward.Quantity}x ")
.Append(new ItemPayload(venture.ItemId))
.Append(venture.Name)
.Append(RawPayload.LinkTerminator)
.Append(new UIForegroundPayload(0))
.Append(" for ")
.Append(new UIForegroundPayload(1))
.Append($"{list.Name} {list.GetIcon()}")
.Append(new UIForegroundPayload(0))
.Append("."));
_pluginLog.Information(
$"Setting AR to use venture {venture.RowId}, which should retrieve {reward.Quantity}x {venture.Name}");
}
private void PrintEndOfListMessage(string retainerName, Configuration.RetainerConfiguration retainer)
{
_chatGui.Print(
new SeString(new UIForegroundPayload(579))
.Append(SeIconChar.Collectible.ToIconString())
.Append(new UIForegroundPayload(0))
.Append($" No tasks left for retainer ")
.Append(new UIForegroundPayload(1))
.Append(retainerName)
.Append(new UIForegroundPayload(0))
.Append(", sending to ")
.Append(new UIForegroundPayload(1))
.Append("Quick Venture")
.Append(new UIForegroundPayload(0))
.Append("."));
_pluginLog.Information($"No tasks left (previous venture = {retainer.LastVenture}), using QV");
}
/// <remarks> /// <remarks>
/// This treats the retainer who is currently doing the venture as 'in-progress', since I believe the /// This treats the retainer who is currently doing the venture as 'in-progress', since I believe the
/// relevant event is fired BEFORE the venture rewards are collected. /// relevant event is fired BEFORE the venture rewards are collected.
@ -378,7 +390,7 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
{ {
if (arguments == "sync") if (arguments == "sync")
Sync(); Sync();
else if (arguments.StartsWith("dnv")) else if (arguments.StartsWith("dnv", StringComparison.Ordinal))
{ {
var ch = _configuration.Characters.SingleOrDefault(x => x.LocalContentId == _clientState.LocalContentId); var ch = _configuration.Characters.SingleOrDefault(x => x.LocalContentId == _clientState.LocalContentId);
if (ch == null || ch.Type == Configuration.CharacterType.NotManaged || ch.Retainers.Count == 0) if (ch == null || ch.Type == Configuration.CharacterType.NotManaged || ch.Retainers.Count == 0)

View File

@ -7,7 +7,7 @@ using FFXIVClientStructs.FFXIV.Client.Game;
namespace ARControl.External; namespace ARControl.External;
public class AllaganToolsIpc internal sealed class AllaganToolsIpc
{ {
private readonly IPluginLog _pluginLog; private readonly IPluginLog _pluginLog;
@ -39,7 +39,7 @@ public class AllaganToolsIpc
_pluginLog.Verbose($"Found {itemCount} items in retainer inventories for itemId {itemId}"); _pluginLog.Verbose($"Found {itemCount} items in retainer inventories for itemId {itemId}");
return itemCount; return itemCount;
} }
catch (IpcError e) catch (IpcError)
{ {
_pluginLog.Warning("Could not query allagantools for retainer inventory counts"); _pluginLog.Warning("Could not query allagantools for retainer inventory counts");
return 0; return 0;

View File

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Globalization;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text; using System.Text;
@ -19,10 +19,11 @@ using ECommons;
using ECommons.ImGuiMethods; using ECommons.ImGuiMethods;
using ImGuiNET; using ImGuiNET;
using LLib; using LLib;
using LLib.ImGui;
namespace ARControl.Windows; namespace ARControl.Windows;
internal sealed class ConfigWindow : LImGui.LWindow internal sealed class ConfigWindow : LWindow
{ {
// TODO This should also allow retainers under max level // TODO This should also allow retainers under max level
private const byte MinLevel = 10; private const byte MinLevel = 10;
@ -316,17 +317,17 @@ internal sealed class ConfigWindow : LImGui.LWindow
var regexMatch = CountAndName.Match(_searchString); var regexMatch = CountAndName.Match(_searchString);
if (regexMatch.Success) if (regexMatch.Success)
{ {
quantity = int.Parse(regexMatch.Groups[1].Value); quantity = int.Parse(regexMatch.Groups[1].Value, CultureInfo.InvariantCulture);
itemName = regexMatch.Groups[2].Value.ToLower(); itemName = regexMatch.Groups[2].Value;
} }
else else
{ {
quantity = 0; quantity = 0;
itemName = _searchString.ToLower(); itemName = _searchString;
} }
foreach (var filtered in _gameCache.Ventures foreach (var filtered in _gameCache.Ventures
.Where(x => x.Name.ToLower().Contains(itemName)) .Where(x => x.Name.Contains(itemName, StringComparison.OrdinalIgnoreCase))
.OrderBy(x => x.Level) .OrderBy(x => x.Level)
.ThenBy(x => x.Name) .ThenBy(x => x.Name)
.ThenBy(x => x.ItemId) .ThenBy(x => x.ItemId)
@ -466,36 +467,15 @@ internal sealed class ConfigWindow : LImGui.LWindow
} }
ImGui.Spacing(); ImGui.Spacing();
List<Configuration.QueuedItem> clipboardItems = new(); List<Configuration.QueuedItem> clipboardItems = ParseClipboardItems();
try ImportFromClipboardButton(list, clipboardItems);
{ RemoveFinishedItemsButton(list);
string? clipboardText = GetClipboardText();
if (!string.IsNullOrWhiteSpace(clipboardText))
{
foreach (var clipboardLine in clipboardText.ReplaceLineEndings().Split(Environment.NewLine))
{
var match = CountAndName.Match(clipboardLine);
if (!match.Success)
continue;
var venture = _gameCache.Ventures.FirstOrDefault(x => ImGui.Spacing();
x.Name.Equals(match.Groups[2].Value, StringComparison.CurrentCultureIgnoreCase)); }
if (venture != null && int.TryParse(match.Groups[1].Value, out int quantity))
{
clipboardItems.Add(new Configuration.QueuedItem
{
ItemId = venture.ItemId,
RemainingQuantity = quantity,
});
}
}
}
}
catch (Exception e)
{
_pluginLog.Warning(e, "Unable to extract clipboard text");
}
private void ImportFromClipboardButton(Configuration.ItemList list, List<Configuration.QueuedItem> clipboardItems)
{
ImGui.BeginDisabled(clipboardItems.Count == 0); ImGui.BeginDisabled(clipboardItems.Count == 0);
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Download, "Import from Clipboard")) if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Download, "Import from Clipboard"))
{ {
@ -540,7 +520,10 @@ internal sealed class ConfigWindow : LImGui.LWindow
ImGui.EndTooltip(); ImGui.EndTooltip();
} }
}
private void RemoveFinishedItemsButton(Configuration.ItemList list)
{
if (list.Items.Count > 0 && list.Type == Configuration.ListType.CollectOneTime) if (list.Items.Count > 0 && list.Type == Configuration.ListType.CollectOneTime)
{ {
ImGui.SameLine(); ImGui.SameLine();
@ -553,8 +536,41 @@ internal sealed class ConfigWindow : LImGui.LWindow
ImGui.EndDisabled(); ImGui.EndDisabled();
} }
}
ImGui.Spacing(); private List<Configuration.QueuedItem> ParseClipboardItems()
{
List<Configuration.QueuedItem> clipboardItems = new List<Configuration.QueuedItem>();
try
{
string? clipboardText = GetClipboardText();
if (!string.IsNullOrWhiteSpace(clipboardText))
{
foreach (var clipboardLine in clipboardText.ReplaceLineEndings().Split(Environment.NewLine))
{
var match = CountAndName.Match(clipboardLine);
if (!match.Success)
continue;
var venture = _gameCache.Ventures.FirstOrDefault(x =>
x.Name.Equals(match.Groups[2].Value, StringComparison.OrdinalIgnoreCase));
if (venture != null && int.TryParse(match.Groups[1].Value, out int quantity))
{
clipboardItems.Add(new Configuration.QueuedItem
{
ItemId = venture.ItemId,
RemainingQuantity = quantity,
});
}
}
}
}
catch (Exception e)
{
_pluginLog.Warning(e, "Unable to extract clipboard text");
}
return clipboardItems;
} }
private void DrawCharacters() private void DrawCharacters()
@ -644,7 +660,8 @@ internal sealed class ConfigWindow : LImGui.LWindow
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (character.ItemListIds == null) if (character.ItemListIds == null)
character.ItemListIds = new(); character.ItemListIds = new();
DrawVentureListSelection(character.LocalContentId.ToString(), DrawVentureListSelection(
character.LocalContentId.ToString(CultureInfo.InvariantCulture),
character.ItemListIds); character.ItemListIds);
} }
else else
@ -890,14 +907,14 @@ internal sealed class ConfigWindow : LImGui.LWindow
private bool IsValidGroupName(string name, Configuration.CharacterGroup? existingGroup) private bool IsValidGroupName(string name, Configuration.CharacterGroup? existingGroup)
{ {
return name.Length >= 2 && return name.Length >= 2 &&
!name.Contains('%') && !name.Contains('%', StringComparison.Ordinal) &&
!_configuration.CharacterGroups.Any(x => x != existingGroup && name.EqualsIgnoreCase(x.Name)); !_configuration.CharacterGroups.Any(x => x != existingGroup && name.EqualsIgnoreCase(x.Name));
} }
private bool IsValidListName(string name, Configuration.ItemList? existingList) private bool IsValidListName(string name, Configuration.ItemList? existingList)
{ {
return name.Length >= 2 && return name.Length >= 2 &&
!name.Contains('%') && !name.Contains('%', StringComparison.Ordinal) &&
!_configuration.ItemLists.Any(x => x != existingList && name.EqualsIgnoreCase(x.Name)); !_configuration.ItemLists.Any(x => x != existingList && name.EqualsIgnoreCase(x.Name));
} }
@ -949,7 +966,7 @@ internal sealed class ConfigWindow : LImGui.LWindow
if (checkPerCharacter) if (checkPerCharacter)
{ {
foreach (var ch in charactersToCheck.Where(x => x.ToCheck(onlyShowMissing).Any())) foreach (var ch in charactersToCheck.Where(x => x.ToCheck(onlyShowMissing).Count != 0))
{ {
bool currentCharacter = _clientState.LocalContentId == ch.Character.LocalContentId; bool currentCharacter = _clientState.LocalContentId == ch.Character.LocalContentId;
ImGui.BeginDisabled(currentCharacter); ImGui.BeginDisabled(currentCharacter);
@ -1027,7 +1044,10 @@ internal sealed class ConfigWindow : LImGui.LWindow
{ {
ImGui.PushFont(UiBuilder.IconFont); ImGui.PushFont(UiBuilder.IconFont);
var pos = ImGui.GetCursorPos(); var pos = ImGui.GetCursorPos();
ImGui.SetCursorPos(pos with { X = pos.X - ImGui.CalcTextSize(CurrentCharPrefix).X - 5 }); ImGui.SetCursorPos(pos with
{
X = pos.X - ImGui.CalcTextSize(CurrentCharPrefix).X - 5
});
ImGui.TextUnformatted(CurrentCharPrefix); ImGui.TextUnformatted(CurrentCharPrefix);
ImGui.SetCursorPos(pos); ImGui.SetCursorPos(pos);
ImGui.PopFont(); ImGui.PopFont();

View File

@ -1,7 +1,7 @@
{ {
"version": 1, "version": 1,
"dependencies": { "dependencies": {
"net7.0-windows7.0": { "net8.0-windows7.0": {
"DalamudPackager": { "DalamudPackager": {
"type": "Direct", "type": "Direct",
"requested": "[2.1.12, )", "requested": "[2.1.12, )",
@ -11,7 +11,7 @@
"autoretainerapi": { "autoretainerapi": {
"type": "Project", "type": "Project",
"dependencies": { "dependencies": {
"ECommons": "[2.1.0.1, )" "ECommons": "[2.1.0.7, )"
} }
}, },
"ecommons": { "ecommons": {

@ -1 +1 @@
Subproject commit 7ff15133ac0d48e9aa57f69524bd9daf36c609bc Subproject commit 6f0aaa55bce6ec79fd4d72f84f21597b39e5445d

@ -1 +1 @@
Subproject commit f1c688a0599b41d70230021328a575da7351cf91 Subproject commit 6c6e6db85dcb28a6bdc3a69fd69f4eef6a8598cf

2
LLib

@ -1 +1 @@
Subproject commit 865a6080319f8ccbcd5fd5b0004404822b6e60d4 Subproject commit 3792244261a9f5426a7916f5a6dd1966238ba84a

View File

@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "7.0.0", "version": "8.0.0",
"rollForward": "latestMinor", "rollForward": "latestMinor",
"allowPrerelease": false "allowPrerelease": false
} }