master v5.0
Liza 2024-03-21 21:59:58 +01:00
parent 1ee347f0ba
commit 3c986562b2
Signed by: liza
GPG Key ID: 7199F8D727D55F67
14 changed files with 1140 additions and 97 deletions

1017
ARDiscard/.editorconfig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<Version>4.7</Version>
<LangVersion>11.0</LangVersion>
<TargetFramework>net8.0-windows</TargetFramework>
<Version>5.0</Version>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
@ -30,7 +30,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dalamud.ContextMenu" Version="1.3.1"/>
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
</ItemGroup>

View File

@ -20,7 +20,7 @@ using LLib;
namespace ARDiscard;
[SuppressMessage("ReSharper", "UnusedType.Global")]
public class AutoDiscardPlogon : IDalamudPlugin
public sealed class AutoDiscardPlogon : IDalamudPlugin
{
private readonly WindowSystem _windowSystem = new(nameof(AutoDiscardPlogon));
private readonly Configuration _configuration;
@ -36,7 +36,10 @@ public class AutoDiscardPlogon : IDalamudPlugin
private readonly InventoryUtils _inventoryUtils;
private readonly IconCache _iconCache;
private readonly AutoRetainerApi _autoRetainerApi;
[SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "Obsolete in ECommons")]
private readonly TaskManager _taskManager;
private readonly ContextMenuIntegration _contextMenuIntegration;
private readonly AutoDiscardIpc _autoDiscardIpc;
@ -44,8 +47,9 @@ public class AutoDiscardPlogon : IDalamudPlugin
public AutoDiscardPlogon(DalamudPluginInterface pluginInterface, ICommandManager commandManager, IChatGui chatGui,
IDataManager dataManager, IClientState clientState, ICondition condition, IPluginLog pluginLog,
IGameGui gameGui, ITextureProvider textureProvider)
IGameGui gameGui, ITextureProvider textureProvider, IContextMenu contextMenu)
{
ArgumentNullException.ThrowIfNull(dataManager);
ItemCache itemCache = new ItemCache(dataManager);
_pluginInterface = pluginInterface;
@ -89,7 +93,7 @@ public class AutoDiscardPlogon : IDalamudPlugin
ECommonsMain.Init(_pluginInterface, this);
_autoRetainerApi = new();
_taskManager = new();
_contextMenuIntegration = new(_pluginInterface, _chatGui, itemCache, _configuration, _configWindow, _gameGui);
_contextMenuIntegration = new(_chatGui, itemCache, _configuration, _configWindow, _gameGui, contextMenu);
_autoDiscardIpc = new(_pluginInterface, _configuration);
_clientState.Login += _discardWindow.Login;
@ -315,7 +319,7 @@ public class AutoDiscardPlogon : IDalamudPlugin
var textNode = addon->UldManager.NodeList[15]->GetAsAtkTextNode();
var text = MemoryHelper.ReadSeString(&textNode->NodeText).ExtractText();
_pluginLog.Information($"YesNo prompt: {text}");
if (text.StartsWith("Discard"))
if (text.StartsWith("Discard", StringComparison.Ordinal))
{
return addon;
}

View File

@ -26,17 +26,17 @@ internal sealed class Configuration : IPluginConfiguration
public sealed class ArmouryConfiguration
{
public bool DiscardFromArmouryChest { get; set; } = false;
public bool CheckMainHandOffHand { get; set; } = false;
public bool CheckLeftSideGear { get; set; } = false;
public bool CheckRightSideGear { get; set; } = false;
public bool DiscardFromArmouryChest { get; set; }
public bool CheckMainHandOffHand { get; set; }
public bool CheckLeftSideGear { get; set; }
public bool CheckRightSideGear { get; set; }
public int MaximumGearItemLevel { get; set; } = 45;
}
public sealed class ContextMenuConfiguration
{
public bool Enabled { get; set; } = true;
public bool OnlyWhenConfigIsOpen { get; set; } = false;
public bool OnlyWhenConfigIsOpen { get; set; }
}
public sealed class PreviewConfiguration

View File

@ -1,10 +1,10 @@
using System;
using ARDiscard.GameData;
using ARDiscard.Windows;
using Dalamud.ContextMenu;
using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
namespace ARDiscard;
@ -16,76 +16,96 @@ internal sealed class ContextMenuIntegration : IDisposable
private readonly Configuration _configuration;
private readonly ConfigWindow _configWindow;
private readonly IGameGui _gameGui;
private readonly SeString _addItemPayload;
private readonly SeString _removeItemPayload;
private readonly InventoryContextMenuItem _addInventoryItem;
private readonly InventoryContextMenuItem _removeInventoryItem;
private readonly DalamudContextMenu _dalamudContextMenu;
private readonly IContextMenu _contextMenu;
private readonly MenuItem _addInventoryItem;
private readonly MenuItem _removeInventoryItem;
public ContextMenuIntegration(DalamudPluginInterface pluginInterface, IChatGui chatGui, ItemCache itemCache,
Configuration configuration, ConfigWindow configWindow, IGameGui gameGui)
public ContextMenuIntegration(IChatGui chatGui, ItemCache itemCache, Configuration configuration,
ConfigWindow configWindow, IGameGui gameGui, IContextMenu contextMenu)
{
_chatGui = chatGui;
_itemCache = itemCache;
_configuration = configuration;
_configWindow = configWindow;
_gameGui = gameGui;
_addItemPayload =
new SeString(new UIForegroundPayload(52))
.Append($"\ue05f ")
.Append(new UIForegroundPayload(0)).Append("Add to Auto Discard List");
_removeItemPayload = new SeString(new UIForegroundPayload(52))
.Append($"\ue05f ")
.Append(new UIForegroundPayload(0)).Append("Remove from Auto Discard List");
_addInventoryItem = new InventoryContextMenuItem(_addItemPayload, AddToDiscardList);
_removeInventoryItem = new InventoryContextMenuItem(_removeItemPayload, RemoveFromDiscardList);
_contextMenu = contextMenu;
_addInventoryItem = new MenuItem
{
Prefix = (SeIconChar)57439,
PrefixColor = 52,
Name = "Add to Auto Discard List",
OnClicked = AddToDiscardList,
};
_removeInventoryItem = new MenuItem
{
Prefix = (SeIconChar)57439,
PrefixColor = 52,
Name = "Remove from Auto Discard List",
OnClicked = RemoveFromDiscardList,
};
_dalamudContextMenu = new(pluginInterface);
_dalamudContextMenu.OnOpenInventoryContextMenu += OpenInventoryContextMenu;
_dalamudContextMenu.OnOpenGameObjectContextMenu += OpenGameObjectContextMenu;
_contextMenu.OnMenuOpened += MenuOpened;
}
private void OpenInventoryContextMenu(InventoryContextMenuOpenArgs args)
private void MenuOpened(MenuOpenedArgs args)
{
if (!IsEnabled())
return;
if (args.ParentAddonName is not ("Inventory" or "InventoryExpansion" or "InventoryLarge" or "ArmouryBoard"))
return;
if (args.Target is MenuTargetInventory targetInventory)
{
if (args.AddonName is not ("Inventory" or "InventoryExpansion" or "InventoryLarge" or "ArmouryBoard") ||
targetInventory.TargetItem == null)
return;
if (!_configWindow.CanItemBeConfigured(args.ItemId))
return;
var item = targetInventory.TargetItem.Value;
if (!_configWindow.CanItemBeConfigured(item.ItemId))
return;
if (_configuration.DiscardingItems.Contains(args.ItemId))
args.AddCustomItem(_removeInventoryItem);
else if (_itemCache.TryGetItem(args.ItemId, out ItemCache.CachedItemInfo? cachedItemInfo) &&
cachedItemInfo.CanBeDiscarded())
args.AddCustomItem(_addInventoryItem);
if (_configuration.DiscardingItems.Contains(item.ItemId))
args.AddMenuItem(_removeInventoryItem);
else if (_itemCache.TryGetItem(item.ItemId, out ItemCache.CachedItemInfo? cachedItemInfo) &&
cachedItemInfo.CanBeDiscarded())
args.AddMenuItem(_addInventoryItem);
}
else
{
if (args.AddonName is not "ChatLog")
return;
uint itemId = (uint)_gameGui.HoveredItem;
if (itemId > 1_000_000)
itemId -= 1_000_000;
if (itemId > 500_000)
itemId -= 500_000;
if (_configuration.DiscardingItems.Contains(itemId))
{
args.AddMenuItem(new MenuItem
{
Prefix = _removeInventoryItem.Prefix,
PrefixColor = _removeInventoryItem.PrefixColor,
Name = _removeInventoryItem.Name,
OnClicked = _ => RemoveFromDiscardList(itemId),
});
}
else if (_itemCache.TryGetItem(itemId, out ItemCache.CachedItemInfo? cachedItemInfo) &&
cachedItemInfo.CanBeDiscarded())
{
args.AddMenuItem(new MenuItem
{
Prefix = _addInventoryItem.Prefix,
PrefixColor = _addInventoryItem.PrefixColor,
Name = _addInventoryItem.Name,
OnClicked = _ => AddToDiscardList(itemId),
});
}
}
}
private void OpenGameObjectContextMenu(GameObjectContextMenuOpenArgs args)
{
if (!IsEnabled())
return;
if (args.ParentAddonName is not "ChatLog")
return;
uint itemId = (uint)_gameGui.HoveredItem;
if (itemId > 1_000_000)
itemId -= 1_000_000;
if (itemId > 500_000)
itemId -= 500_000;
if (_configuration.DiscardingItems.Contains(itemId))
args.AddCustomItem(new GameObjectContextMenuItem(_removeItemPayload, _ => RemoveFromDiscardList(itemId)));
else if (_itemCache.TryGetItem(itemId, out ItemCache.CachedItemInfo? cachedItemInfo) &&
cachedItemInfo.CanBeDiscarded())
args.AddCustomItem(new GameObjectContextMenuItem(_addItemPayload, _ => AddToDiscardList(itemId)));
}
private void AddToDiscardList(InventoryContextMenuItemSelectedArgs args) => AddToDiscardList(args.ItemId);
private void AddToDiscardList(MenuItemClickedArgs args) =>
AddToDiscardList(((MenuTargetInventory)args.Target).TargetItem!.Value.ItemId);
private void AddToDiscardList(uint itemId)
{
@ -104,7 +124,8 @@ internal sealed class ContextMenuIntegration : IDisposable
}
}
private void RemoveFromDiscardList(InventoryContextMenuItemSelectedArgs args) => RemoveFromDiscardList(args.ItemId);
private void RemoveFromDiscardList(MenuItemClickedArgs args) =>
RemoveFromDiscardList(((MenuTargetInventory)args.Target).TargetItem!.Value.ItemId);
private void RemoveFromDiscardList(uint itemId)
{
@ -136,8 +157,6 @@ internal sealed class ContextMenuIntegration : IDisposable
public void Dispose()
{
_dalamudContextMenu.OnOpenGameObjectContextMenu -= OpenGameObjectContextMenu;
_dalamudContextMenu.OnOpenInventoryContextMenu -= OpenInventoryContextMenu;
_dalamudContextMenu.Dispose();
_contextMenu.OnMenuOpened -= MenuOpened;
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
@ -79,7 +80,7 @@ internal sealed class InventoryUtils
.ToList();
}
private unsafe IEnumerable<ItemWrapper> GetArmouryItemsToDiscard(bool condition, InventoryManager* inventoryManager,
private unsafe ReadOnlyCollection<ItemWrapper> GetArmouryItemsToDiscard(bool condition, InventoryManager* inventoryManager,
InventoryType[] inventoryTypes, Dictionary<uint, uint> itemCounts, List<uint>? gearsetItems)
{
List<ItemWrapper> items = new();
@ -89,7 +90,7 @@ internal sealed class InventoryUtils
items.AddRange(GetItemsToDiscard(inventoryManager, inventoryType, itemCounts, gearsetItems));
}
return items;
return items.AsReadOnly();
}
public unsafe InventoryItem* GetNextItemToDiscard(ItemFilter? itemFilter)
@ -100,7 +101,7 @@ internal sealed class InventoryUtils
return toDiscard != null ? toDiscard.InventoryItem : null;
}
private unsafe IReadOnlyList<ItemWrapper> GetItemsToDiscard(InventoryManager* inventoryManager,
private unsafe ReadOnlyCollection<ItemWrapper> GetItemsToDiscard(InventoryManager* inventoryManager,
InventoryType inventoryType, Dictionary<uint, uint> itemCounts,
IReadOnlyList<uint>? gearsetItems)
{
@ -150,7 +151,7 @@ internal sealed class InventoryUtils
}
}
return toDiscard;
return toDiscard.AsReadOnly();
}
private unsafe List<uint>? GetAllGearsetItems()
@ -195,7 +196,7 @@ internal sealed class InventoryUtils
{
if (InternalConfiguration.BlacklistedItems.Contains(item->ItemID) ||
InternalConfiguration.UltimateWeapons.Contains(item->ItemID))
throw new Exception($"Can't discard {item->ItemID}");
throw new ArgumentException($"Can't discard {item->ItemID}", nameof(item));
AgentInventoryContext.Instance()->DiscardItem(item, item->Container, item->Slot, 0);
}

View File

@ -2,9 +2,9 @@
namespace ARDiscard.GameData;
internal class ItemFilter
internal sealed class ItemFilter
{
public static ItemFilter? None = null;
public const ItemFilter? None = null;
public required List<uint> ItemIds { get; init; }
}

View File

@ -10,11 +10,11 @@ using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using ECommons;
using ImGuiNET;
using LLib;
using LLib.ImGui;
namespace ARDiscard.Windows;
internal sealed class ConfigWindow : LImGui.LWindow
internal sealed class ConfigWindow : LWindow
{
private const int ResultLimit = 200;
@ -27,7 +27,7 @@ internal sealed class ConfigWindow : LImGui.LWindow
private List<(uint ItemId, string Name)> _searchResults = new();
private List<(uint ItemId, string Name)> _discarding = new();
private List<(uint ItemId, string Name)>? _allItems = null;
private List<(uint ItemId, string Name)>? _allItems;
private bool _resetKeyboardFocus = true;
public event EventHandler? DiscardNowClicked;
@ -172,7 +172,7 @@ internal sealed class ConfigWindow : LImGui.LWindow
ImGui.Separator();
List<(uint, string)> toRemove = new();
foreach (var (id, name) in _discarding.OrderBy(x => x.Name.ToLower()))
foreach (var (id, name) in _discarding.OrderBy(x => x.Name, StringComparer.OrdinalIgnoreCase))
{
if (ImGui.Selectable(name, true))
toRemove.Add((id, name));

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ARDiscard.GameData;
using Dalamud.Game.ClientState.Conditions;
@ -9,10 +10,11 @@ using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Common.Math;
using ImGuiNET;
using LLib;
using LLib.ImGui;
namespace ARDiscard.Windows;
internal sealed class DiscardWindow : LImGui.LWindow
internal sealed class DiscardWindow : LWindow
{
private readonly InventoryUtils _inventoryUtils;
private readonly ItemCache _itemCache;
@ -47,7 +49,7 @@ internal sealed class DiscardWindow : LImGui.LWindow
};
}
public bool Locked { get; set; } = false;
public bool Locked { get; set; }
public override void Draw()
{
@ -98,7 +100,7 @@ internal sealed class DiscardWindow : LImGui.LWindow
ImGui.BeginDisabled(Locked ||
!_clientState.IsLoggedIn ||
!(_condition[ConditionFlag.NormalConditions] || _condition[ConditionFlag.Mounted]) ||
_displayedItems.Count(x => x.Selected) == 0 ||
!_displayedItems.Any(x => x.Selected) ||
DiscardAllClicked == null);
if (ImGui.Button("Discard all selected items"))
{
@ -162,7 +164,7 @@ internal sealed class DiscardWindow : LImGui.LWindow
UiCategoryName = x.Key.ItemInfo!.UiCategoryName,
Selected = !notSelected.Contains(x.Key.ItemId),
})
.OrderBy(x => x.Name.ToLower())
.OrderBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
.ToList();
}

View File

@ -1,13 +1,7 @@
{
"version": 1,
"dependencies": {
"net7.0-windows7.0": {
"Dalamud.ContextMenu": {
"type": "Direct",
"requested": "[1.3.1, )",
"resolved": "1.3.1",
"contentHash": "ptAxut5PiLnzZ4G/KQdHJVcyklC/BF3otHJ7zYVUPiKBjsOCoF0n/6h2jK7e+8ev2Y1yAY3Wtx2GuXLFQgt9Uw=="
},
"net8.0-windows7.0": {
"DalamudPackager": {
"type": "Direct",
"requested": "[2.1.12, )",
@ -17,7 +11,7 @@
"autoretainerapi": {
"type": "Project",
"dependencies": {
"ECommons": "[2.1.0, )"
"ECommons": "[2.1.0.7, )"
}
},
"ecommons": {

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

@ -1 +1 @@
Subproject commit f1c688a0599b41d70230021328a575da7351cf91
Subproject commit d238d4188e8b47b11252d75cb5e4b678b8da2756

2
LLib

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

7
global.json Normal file
View File

@ -0,0 +1,7 @@
{
"sdk": {
"version": "8.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
}
}