Compare commits

..

No commits in common. "master" and "v1.0" have entirely different histories.
master ... v1.0

4 changed files with 70 additions and 164 deletions

View File

@ -8,7 +8,6 @@ using Dalamud.Game.Command;
using Dalamud.Game.Gui.Dtr; using Dalamud.Game.Gui.Dtr;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Dalamud.Plugin.Ipc.Exceptions;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
@ -77,42 +76,34 @@ internal sealed class CharacterSwitch : IDisposable
private Target? FindCharacter(int direction, bool showError = true) private Target? FindCharacter(int direction, bool showError = true)
{ {
try _pluginLog.Verbose($"Switching characters ({direction})");
{
_pluginLog.Verbose($"Switching characters ({direction})");
var characterIds = _autoRetainerApi.GetRegisteredCharacters(); var characterIds = _autoRetainerApi.GetRegisteredCharacters();
int index = characterIds.IndexOf(_clientState.LocalContentId); int index = characterIds.IndexOf(_clientState.LocalContentId);
if (index < 0) if (index < 0)
{
if (showError)
_chatGui.PrintError("[KitchenSink] Current character not known.");
return null;
}
OfflineCharacterData? target;
do
{
index = (index + direction + characterIds.Count) % characterIds.Count;
target = _autoRetainerApi.GetOfflineCharacterData(characterIds[index]);
if (target?.CID == _clientState.LocalContentId)
{ {
if (showError) if (showError)
_chatGui.PrintError("[KitchenSink] Current character not known."); _chatGui.PrintError("[KitchenSink] No character to switch to found.");
return null; return null;
} }
OfflineCharacterData? target; if (target is { ExcludeRetainer: true, ExcludeWorkshop: true })
do target = null;
{ } while (target == null);
index = (index + direction + characterIds.Count) % characterIds.Count;
target = _autoRetainerApi.GetOfflineCharacterData(characterIds[index]);
if (target?.CID == _clientState.LocalContentId)
{
if (showError)
_chatGui.PrintError("[KitchenSink] No character to switch to found.");
return null;
}
if (target is { ExcludeRetainer: true, ExcludeWorkshop: true }) return new Target(target.Name, target.World);
target = null;
} while (target == null);
return new Target(target.Name, target.World);
}
catch (IpcError)
{
_chatGui.PrintError("Could not switch character, AutoRetainer API isn't available.");
return null;
}
} }
private void NextCharacter(string command, string arguments) => SwitchCharacter(FindCharacter(1)); private void NextCharacter(string command, string arguments) => SwitchCharacter(FindCharacter(1));
@ -127,34 +118,26 @@ internal sealed class CharacterSwitch : IDisposable
return; return;
} }
try string[] args = arguments.Split(' ', 2);
if (args.Length < 2 || !int.TryParse(args[1], CultureInfo.InvariantCulture, out int index))
index = 1;
var targets = _autoRetainerApi.GetRegisteredCharacters()
.Select(characterId => _autoRetainerApi.GetOfflineCharacterData(characterId))
.Where(x => !x.ExcludeRetainer || !x.ExcludeWorkshop)
.Select(x => new { x.Name, x.World })
.ToList();
var target = targets.Where(x => x.World.StartsWith(args[0], StringComparison.OrdinalIgnoreCase)).Skip(index - 1)
.FirstOrDefault() ??
targets.FirstOrDefault(x => x.Name.Contains(arguments, StringComparison.OrdinalIgnoreCase));
if (target == null)
{ {
string[] args = arguments.Split(' ', 2); _chatGui.PrintError($"[KitchenSink] No character found on world {args[0]} with #{index}.");
if (args.Length < 2 || !int.TryParse(args[1], CultureInfo.InvariantCulture, out int index)) return;
index = 1;
var targets = _autoRetainerApi.GetRegisteredCharacters()
.Select(characterId => _autoRetainerApi.GetOfflineCharacterData(characterId))
.Where(x => !x.ExcludeRetainer || !x.ExcludeWorkshop)
.Select(x => new { x.Name, x.World })
.ToList();
var target = targets.Where(x => x.World.StartsWith(args[0], StringComparison.OrdinalIgnoreCase))
.Skip(index - 1)
.FirstOrDefault() ??
targets.FirstOrDefault(x => x.Name.Contains(arguments, StringComparison.OrdinalIgnoreCase));
if (target == null)
{
_chatGui.PrintError($"[KitchenSink] No character found on world {args[0]} with #{index}.");
return;
}
SwitchCharacter(new Target(target.Name, target.World));
}
catch (IpcError)
{
_chatGui.PrintError("Could not switch character, AutoRetainer API isn't available.");
} }
SwitchCharacter(new Target(target.Name, target.World));
} }
private void SwitchCharacter(Target? target) private void SwitchCharacter(Target? target)
@ -191,45 +174,32 @@ internal sealed class CharacterSwitch : IDisposable
private void UpdateDtrBar() private void UpdateDtrBar()
{ {
if (_dtrBarEntry.UserHidden) string? currentWorld = _clientState.LocalPlayer?.CurrentWorld.GameData?.Name?.ToString();
return; string? homeWorld = _clientState.LocalPlayer?.HomeWorld.GameData?.Name?.ToString();
var characterIds = _autoRetainerApi.GetRegisteredCharacters() ?? new();
var characterIdsOnHomeWorld = characterIds
.Where(x => _autoRetainerApi.GetOfflineCharacterData(x)?.World == homeWorld).ToList();
try SeIconChar seIconChar = SeIconChar.Instance1 + characterIdsOnHomeWorld.IndexOf(_clientState.LocalContentId);
if (currentWorld == homeWorld)
{ {
string? currentWorld = _clientState.LocalPlayer?.CurrentWorld.GameData?.Name?.ToString(); _dtrBarEntry.Text = seIconChar.ToIconString();
string? homeWorld = _clientState.LocalPlayer?.HomeWorld.GameData?.Name?.ToString();
var characterIds = _autoRetainerApi.GetRegisteredCharacters() ?? new();
var characterIdsOnHomeWorld = characterIds
.Where(x => _autoRetainerApi.GetOfflineCharacterData(x)?.World == homeWorld).ToList();
SeIconChar seIconChar = SeIconChar.Instance1 + characterIdsOnHomeWorld.IndexOf(_clientState.LocalContentId); var previous = FindCharacter(-1, showError: false);
if (currentWorld == homeWorld) var next = FindCharacter(1, showError: false);
{ if (previous != null && next != null)
_dtrBarEntry.Text = seIconChar.ToIconString(); _dtrBarEntry.Tooltip = $"Prev: {previous.ToString(homeWorld)}\nNext: {next.ToString(homeWorld)}";
else if (previous != null)
var previous = FindCharacter(-1, showError: false); _dtrBarEntry.Tooltip = $"Prev: {previous.ToString(homeWorld)}";
var next = FindCharacter(1, showError: false); else if (next != null)
if (previous != null && next != null) _dtrBarEntry.Tooltip = $"Next: {next.ToString(homeWorld)}";
_dtrBarEntry.Tooltip = $"Prev: {previous.ToString(homeWorld)}\nNext: {next.ToString(homeWorld)}";
else if (previous != null)
_dtrBarEntry.Tooltip = $"Prev: {previous.ToString(homeWorld)}";
else if (next != null)
_dtrBarEntry.Tooltip = $"Next: {next.ToString(homeWorld)}";
else
_dtrBarEntry.Tooltip = null;
}
else else
{ _dtrBarEntry.Tooltip = null;
_dtrBarEntry.Text = $"{homeWorld} {seIconChar.ToIconString()}";
_dtrBarEntry.Tooltip = $"Return to {homeWorld}";
}
if (!_dtrBarEntry.Shown)
_dtrBarEntry.Shown = true;
} }
catch (IpcError) else
{ {
_dtrBarEntry.Shown = false; _dtrBarEntry.Text = $"{homeWorld} {seIconChar.ToIconString()}";
_dtrBarEntry.Tooltip = $"Return to {homeWorld}";
} }
} }

View File

@ -1,17 +1,14 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Reflection;
using Dalamud.Game.Command; using Dalamud.Game.Command;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game;
using LLib;
namespace KitchenSink.Commands; namespace KitchenSink.Commands;
@ -25,41 +22,24 @@ internal sealed class DropboxQueue : IDisposable
InventoryType.Inventory4, InventoryType.Inventory4,
InventoryType.Crystals, InventoryType.Crystals,
InventoryType.Currency, InventoryType.Currency,
InventoryType.ArmoryMainHand,
InventoryType.ArmoryOffHand,
InventoryType.ArmoryHead,
InventoryType.ArmoryBody,
InventoryType.ArmoryHands,
InventoryType.ArmoryLegs,
InventoryType.ArmoryFeets,
InventoryType.ArmoryEar,
InventoryType.ArmoryNeck,
InventoryType.ArmoryWrist,
InventoryType.ArmoryRings,
]; ];
private readonly ICommandManager _commandManager; private readonly ICommandManager _commandManager;
private readonly IChatGui _chatGui; private readonly IChatGui _chatGui;
private readonly DropboxApi _dropboxApi; private readonly DropboxApi _dropboxApi;
public DropboxQueue(IDalamudPluginInterface pluginInterface, public DropboxQueue(IDalamudPluginInterface pluginInterface, ICommandManager commandManager, IChatGui chatGui,
DalamudReflector reflector,
ICommandManager commandManager,
IChatGui chatGui,
IPluginLog pluginLog) IPluginLog pluginLog)
{ {
_commandManager = commandManager; _commandManager = commandManager;
_chatGui = chatGui; _chatGui = chatGui;
_dropboxApi = new DropboxApi(pluginInterface, reflector, pluginLog); _dropboxApi = new DropboxApi(pluginInterface, pluginLog);
_commandManager.AddHandler("/dbq", new CommandInfo(Queue) _commandManager.AddHandler("/dbq", new CommandInfo(Queue)
{ {
HelpMessage = HelpMessage =
$"Queue items to be imported into dropbox{Environment.NewLine}" + $"Queue items to be imported into dropbox{Environment.NewLine}" +
$"\t/dbq item1:qty1 item2:qty2 [...] - queues items for the next trade (use * as quantity for 'all'){Environment.NewLine}" + $"\t/dbq item1:qty1 item2:qty2 [...] - queues items for the next trade (use * as quantity for 'all'){Environment.NewLine}n" +
$"\t/dbq clear - remove all items in the queue{Environment.NewLine}" + $"\t/dbq clear - remove all items in the queue{Environment.NewLine}" +
$"\t/dbq request item1:qty1 item2:qty2 [...] - show the command to fill your inventory with the specific item quantities{Environment.NewLine}" + $"\t/dbq request item1:qty1 item2:qty2 [...] - show the command to fill your inventory with the specific item quantities{Environment.NewLine}" +
$"\t/dbq [shards/crystals/shards+crystals] - show the command to fill shards and/or crystals to 9999" $"\t/dbq [shards/crystals/shards+crystals] - show the command to fill shards and/or crystals to 9999"
@ -71,35 +51,20 @@ internal sealed class DropboxQueue : IDisposable
string[] parts = arguments.Split(" ", 2); string[] parts = arguments.Split(" ", 2);
switch (parts[0]) switch (parts[0])
{ {
case "*s":
case "shards": case "shards":
BuildRequest(string.Join(" ", Enumerable.Range(2, 6).Select(x => $"{x}:9999"))); BuildRequest(string.Join(" ", Enumerable.Range(2, 6).Select(x => $"{x}:9999")));
break; break;
case "*c":
case "crystals": case "crystals":
BuildRequest(string.Join(" ", Enumerable.Range(8, 6).Select(x => $"{x}:9999"))); BuildRequest(string.Join(" ", Enumerable.Range(8, 6).Select(x => $"{x}:9999")));
break; break;
case "*x":
case "clusters":
BuildRequest(string.Join(" ", Enumerable.Range(14, 6).Select(x => $"{x}:9999")));
break;
case "*sc":
case "shards+crystals": case "shards+crystals":
BuildRequest(string.Join(" ", Enumerable.Range(2, 12).Select(x => $"{x}:9999"))); BuildRequest(string.Join(" ", Enumerable.Range(2, 12).Select(x => $"{x}:9999")));
break; break;
case "*cx":
case "crystals+clusters":
BuildRequest(string.Join(" ", Enumerable.Range(8, 12).Select(x => $"{x}:9999")));
break;
case "*scx":
case "shards+crystals+clusters":
BuildRequest(string.Join(" ", Enumerable.Range(2, 18).Select(x => $"{x}:9999")));
break;
case "request": case "request":
BuildRequest(parts.Length == 2 ? parts[1] : string.Empty); BuildRequest(parts.Length == 2 ? parts[1] : string.Empty);
break; break;
case "clear": case "clear":
_dropboxApi.ClearQueue(); //_dropboxApi.ClearQueue();
break; break;
default: default:
AddToQueue(arguments); AddToQueue(arguments);
@ -125,9 +90,7 @@ internal sealed class DropboxQueue : IDisposable
var missingItems = parsedItems var missingItems = parsedItems
.Select(item => item with .Select(item => item with
{ {
Needed = item.Needed - DefaultInventoryTypes.Sum(y => Needed = item.Needed - inventoryManger->GetItemCountInContainer(item.ItemId, InventoryType.Crystals)
inventoryManger->GetItemCountInContainer(item.ItemId, y) +
inventoryManger->GetItemCountInContainer(item.ItemId, y, true))
}) })
.Where(x => x.Needed > 0) .Where(x => x.Needed > 0)
.ToList(); .ToList();
@ -270,15 +233,13 @@ internal sealed class DropboxQueue : IDisposable
private sealed class DropboxApi private sealed class DropboxApi
{ {
private readonly DalamudReflector _reflector;
private readonly IPluginLog _pluginLog; private readonly IPluginLog _pluginLog;
private readonly ICallGateSubscriber<object> _beginTradingQueue; private readonly ICallGateSubscriber<object> _beginTradingQueue;
private readonly ICallGateSubscriber<uint, bool, int> _getItemQuantity; private readonly ICallGateSubscriber<uint,bool,int> _getItemQuantity;
private readonly ICallGateSubscriber<uint, bool, int, object> _setItemQuantity; private readonly ICallGateSubscriber<uint,bool,int, object> _setItemQuantity;
public DropboxApi(IDalamudPluginInterface pluginInterface, DalamudReflector reflector, IPluginLog pluginLog) public DropboxApi(IDalamudPluginInterface pluginInterface, IPluginLog pluginLog)
{ {
_reflector = reflector;
_pluginLog = pluginLog; _pluginLog = pluginLog;
_beginTradingQueue = pluginInterface.GetIpcSubscriber<object>("Dropbox.BeginTradingQueue"); _beginTradingQueue = pluginInterface.GetIpcSubscriber<object>("Dropbox.BeginTradingQueue");
@ -297,27 +258,5 @@ internal sealed class DropboxQueue : IDisposable
int currentQuantity = _getItemQuantity.InvokeFunc(itemId, hq); int currentQuantity = _getItemQuantity.InvokeFunc(itemId, hq);
_setItemQuantity.InvokeAction(itemId, hq, quantity + currentQuantity); _setItemQuantity.InvokeAction(itemId, hq, quantity + currentQuantity);
} }
public void ClearQueue()
{
if (TryGetItemQuantities(out _, out IDictionary? itemQuantities))
itemQuantities.Clear();
}
private bool TryGetItemQuantities([NotNullWhen(true)] out IDalamudPlugin? dropboxPlugin,
[NotNullWhen(true)] out IDictionary? itemQuantities)
{
if (!_reflector.TryGetDalamudPlugin("Dropbox", out dropboxPlugin))
{
itemQuantities = null;
return false;
}
var itemQueueUiType = dropboxPlugin.GetType().Assembly.GetType("Dropbox.ItemQueueUI")!;
itemQuantities =
(IDictionary?)itemQueueUiType.GetField("ItemQuantities", BindingFlags.Public | BindingFlags.Static)!
.GetValue(null);
return itemQuantities != null;
}
} }
} }

View File

@ -1,6 +1,6 @@
<Project Sdk="Dalamud.NET.Sdk/9.0.2"> <Project Sdk="Dalamud.NET.Sdk/9.0.2">
<PropertyGroup> <PropertyGroup>
<Version>1.2</Version> <Version>1.0</Version>
<OutputPath>dist</OutputPath> <OutputPath>dist</OutputPath>
</PropertyGroup> </PropertyGroup>

View File

@ -4,7 +4,6 @@ using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using ECommons; using ECommons;
using KitchenSink.Commands; using KitchenSink.Commands;
using LLib;
namespace KitchenSink; namespace KitchenSink;
@ -18,15 +17,13 @@ internal sealed class KitchenSinkPlugin : IDalamudPlugin
public KitchenSinkPlugin(IDalamudPluginInterface pluginInterface, ICommandManager commandManager, public KitchenSinkPlugin(IDalamudPluginInterface pluginInterface, ICommandManager commandManager,
IClientState clientState, IChatGui chatGui, INotificationManager notificationManager, IDtrBar dtrBar, IClientState clientState, IChatGui chatGui, INotificationManager notificationManager, IDtrBar dtrBar,
ICondition condition, IFramework framework, IPluginLog pluginLog) ICondition condition, IPluginLog pluginLog)
{ {
DalamudReflector reflector = new DalamudReflector(pluginInterface, framework, pluginLog);
ECommonsMain.Init(pluginInterface, this); ECommonsMain.Init(pluginInterface, this);
_autoRetainerApi = new AutoRetainerApi(); _autoRetainerApi = new AutoRetainerApi();
_characterSwitch = new CharacterSwitch(_autoRetainerApi, commandManager, clientState, chatGui, _characterSwitch = new CharacterSwitch(_autoRetainerApi, commandManager, clientState, chatGui,
notificationManager, dtrBar, condition, pluginLog); notificationManager, dtrBar, condition, pluginLog);
_dropboxQueue = new DropboxQueue(pluginInterface, reflector, commandManager, chatGui, pluginLog); _dropboxQueue = new DropboxQueue(pluginInterface, commandManager, chatGui, pluginLog);
} }
public void Dispose() public void Dispose()