Character exclusions

This commit is contained in:
Liza 2023-09-10 13:34:58 +02:00
parent 262e146a69
commit 03a79baaa2
Signed by: liza
GPG Key ID: 7199F8D727D55F67
5 changed files with 201 additions and 69 deletions

View File

@ -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>1.3</Version> <Version>1.4</Version>
<LangVersion>11.0</LangVersion> <LangVersion>11.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Linq;
using AutoRetainerAPI; using AutoRetainerAPI;
using ClickLib.Clicks; using ClickLib.Clicks;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command; using Dalamud.Game.Command;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
@ -25,17 +27,19 @@ public class AutoDiscardPlogon : IDalamudPlugin
private readonly DalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly ChatGui _chatGui; private readonly ChatGui _chatGui;
private readonly ClientState _clientState;
private readonly CommandManager _commandManager; private readonly CommandManager _commandManager;
private readonly InventoryUtils _inventoryUtils; private readonly InventoryUtils _inventoryUtils;
private readonly AutoRetainerApi _autoRetainerApi; private readonly AutoRetainerApi _autoRetainerApi;
private readonly TaskManager _taskManager; private readonly TaskManager _taskManager;
public AutoDiscardPlogon(DalamudPluginInterface pluginInterface, CommandManager commandManager, ChatGui chatGui, public AutoDiscardPlogon(DalamudPluginInterface pluginInterface, CommandManager commandManager, ChatGui chatGui,
DataManager dataManager) DataManager dataManager, ClientState clientState)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration(); _configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration();
_chatGui = chatGui; _chatGui = chatGui;
_clientState = clientState;
_commandManager = commandManager; _commandManager = commandManager;
_commandManager.AddHandler("/discardconfig", new CommandInfo(OpenConfig)); _commandManager.AddHandler("/discardconfig", new CommandInfo(OpenConfig));
_commandManager.AddHandler("/discardall", new CommandInfo(ProcessCommand)); _commandManager.AddHandler("/discardall", new CommandInfo(ProcessCommand));
@ -43,7 +47,7 @@ public class AutoDiscardPlogon : IDalamudPlugin
_pluginInterface.UiBuilder.Draw += _windowSystem.Draw; _pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
_pluginInterface.UiBuilder.OpenConfigUi += OpenConfigUi; _pluginInterface.UiBuilder.OpenConfigUi += OpenConfigUi;
_configWindow = new(_pluginInterface, _configuration, dataManager); _configWindow = new(_pluginInterface, _configuration, dataManager, clientState);
_windowSystem.AddWindow(_configWindow); _windowSystem.AddWindow(_configWindow);
ECommonsMain.Init(_pluginInterface, this); ECommonsMain.Init(_pluginInterface, this);
@ -58,8 +62,23 @@ public class AutoDiscardPlogon : IDalamudPlugin
private unsafe void CheckPostProcess(string retainerName) private unsafe void CheckPostProcess(string retainerName)
{ {
if (_configuration.RunAfterVenture && _inventoryUtils.GetNextItemToDiscard() != null) if (!_configuration.RunAfterVenture)
{
PluginLog.Information($"Not running post-venture tasks for {retainerName}, disabled globally");
}
else if (_configuration.ExcludedCharacters.Any(x => x.LocalContentId == _clientState.LocalContentId))
{
PluginLog.Information($"Not running post-venture tasks for {retainerName}, disabled for current character");
}
else if (_inventoryUtils.GetNextItemToDiscard() == null)
{
PluginLog.Information($"Not running post-venture tasks for {retainerName}, no items to discard");
}
else
{
PluginLog.Information($"Requesting post-processing for {retainerName}");
_autoRetainerApi.RequestPostprocess(); _autoRetainerApi.RequestPostprocess();
}
} }
private void DoPostProcess(string retainerName) private void DoPostProcess(string retainerName)

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Game.ClientState;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Plugin; using Dalamud.Plugin;
using ECommons; using ECommons;
@ -16,6 +18,7 @@ public class ConfigWindow : Window
private readonly DalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly DataManager _dataManager; private readonly DataManager _dataManager;
private readonly ClientState _clientState;
private string _itemName = string.Empty; private string _itemName = string.Empty;
private List<(uint ItemId, string Name)> _searchResults = new(); private List<(uint ItemId, string Name)> _searchResults = new();
@ -23,12 +26,14 @@ public class ConfigWindow : Window
private List<(uint ItemId, string Name)>? _allItems = null; private List<(uint ItemId, string Name)>? _allItems = null;
private bool _resetKeyboardFocus = true; private bool _resetKeyboardFocus = true;
public ConfigWindow(DalamudPluginInterface pluginInterface, Configuration configuration, DataManager dataManager) public ConfigWindow(DalamudPluginInterface pluginInterface, Configuration configuration, DataManager dataManager,
ClientState clientState)
: base("Auto Discard###AutoDiscardConfig") : base("Auto Discard###AutoDiscardConfig")
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_configuration = configuration; _configuration = configuration;
_dataManager = dataManager; _dataManager = dataManager;
_clientState = clientState;
Size = new Vector2(600, 400); Size = new Vector2(600, 400);
SizeCondition = ImGuiCond.FirstUseEver; SizeCondition = ImGuiCond.FirstUseEver;
@ -46,97 +51,189 @@ public class ConfigWindow : Window
public override void Draw() public override void Draw()
{ {
bool runAfterVenture = _configuration.RunAfterVenture; bool runAfterVenture = _configuration.RunAfterVenture;
if (ImGui.Checkbox("Run automatically after AutoRetainer's venture", ref runAfterVenture)) if (ImGui.Checkbox("[Global] Run automatically after AutoRetainer's venture", ref runAfterVenture))
{ {
_configuration.RunAfterVenture = runAfterVenture; _configuration.RunAfterVenture = runAfterVenture;
_pluginInterface.SavePluginConfig(_configuration); Save();
} }
var ws = ImGui.GetWindowSize(); if (ImGui.BeginTabBar("AutoDiscardTabs"))
if (ImGui.BeginChild("Left", new Vector2(Math.Max(10, ws.X / 2), -1), true))
{ {
ImGui.Text("Search"); DrawDiscardList();
ImGui.SetNextItemWidth(ws.X / 2 - 20); DrawExcludedCharacters();
if (_resetKeyboardFocus)
ImGui.EndTabBar();
}
}
private void DrawDiscardList()
{
if (ImGui.BeginTabItem("Items to Discard"))
{
var ws = ImGui.GetWindowSize();
if (ImGui.BeginChild("Left", new Vector2(Math.Max(10, ws.X / 2), -1), true))
{ {
ImGui.SetKeyboardFocusHere(); ImGui.Text("Search");
_resetKeyboardFocus = false; ImGui.SetNextItemWidth(ws.X / 2 - 20);
if (_resetKeyboardFocus)
{
ImGui.SetKeyboardFocusHere();
_resetKeyboardFocus = false;
}
string previousName = _itemName;
if (ImGui.InputText("", ref _itemName, 256, ImGuiInputTextFlags.EnterReturnsTrue))
{
_resetKeyboardFocus = true;
if (_searchResults.Count > 0)
{
var itemToAdd = _searchResults.FirstOrDefault();
if (_discarding.All(x => x.ItemId != itemToAdd.ItemId))
{
_discarding.Add(itemToAdd);
}
else
{
_discarding.Remove(itemToAdd);
}
Save();
}
}
if (previousName != _itemName)
UpdateResults();
ImGui.Separator();
if (string.IsNullOrEmpty(_itemName))
{
ImGui.Text("Type item name...");
}
foreach (var (id, name) in _searchResults)
{
bool selected = _discarding.Any(x => x.Item1 == id);
if (ImGui.Selectable(name, selected))
{
if (!selected)
{
_discarding.Add((id, name));
}
else
{
_discarding.Remove((id, name));
}
Save();
}
}
} }
string previousName = _itemName; ImGui.EndChild();
if (ImGui.InputText("", ref _itemName, 256, ImGuiInputTextFlags.EnterReturnsTrue)) ImGui.SameLine();
if (ImGui.BeginChild("Right", new Vector2(-1, -1), true, ImGuiWindowFlags.NoSavedSettings))
{ {
_resetKeyboardFocus = true; ImGui.Text("Items that will be automatically discarded");
if (_searchResults.Count > 0) ImGui.Separator();
List<(uint, string)> toRemove = new();
foreach (var (id, name) in _discarding.OrderBy(x => x.Name.ToLower()))
{ {
var itemToAdd = _searchResults.FirstOrDefault(); if (ImGui.Selectable(name, true))
if (_discarding.All(x => x.ItemId != itemToAdd.ItemId)) toRemove.Add((id, name));
{ }
_discarding.Add(itemToAdd);
} if (toRemove.Count > 0)
else {
{ foreach (var tr in toRemove)
_discarding.Remove(itemToAdd); _discarding.Remove(tr);
}
Save(); Save();
} }
} }
if (previousName != _itemName) ImGui.EndChild();
UpdateResults(); ImGui.EndTabItem();
}
}
ImGui.Separator(); private void DrawExcludedCharacters()
{
if (string.IsNullOrEmpty(_itemName)) if (ImGui.BeginTabItem("Excluded Characters"))
{
if (_clientState.IsLoggedIn && _clientState.LocalContentId > 0)
{ {
ImGui.Text("Type item name..."); string worldName = _clientState.LocalPlayer?.HomeWorld.GameData?.Name ?? "??";
} ImGui.TextWrapped(
$"Current Character: {_clientState.LocalPlayer?.Name} @ {worldName} ({_clientState.LocalContentId:X})");
foreach (var (id, name) in _searchResults) ImGui.Indent(30);
{ if (_configuration.ExcludedCharacters.Any(x => x.LocalContentId == _clientState.LocalContentId))
bool selected = _discarding.Any(x => x.Item1 == id);
if (ImGui.Selectable(name, selected))
{ {
if (!selected) ImGui.TextColored(ImGuiColors.DalamudRed, "This character is currently excluded.");
if (ImGui.Button("Remove exclusion"))
{ {
_discarding.Add((id, name)); _configuration.ExcludedCharacters.RemoveAll(
c => c.LocalContentId == _clientState.LocalContentId);
Save();
}
}
else
{
if (_configuration.RunAfterVenture)
{
ImGui.TextColored(ImGuiColors.HealerGreen,
"This character is currently included (and will be post-processed in autoretainer).");
} }
else else
{ {
_discarding.Remove((id, name)); ImGui.TextColored(ImGuiColors.DalamudYellow,
"This character is currently included (but running post-processing is disabled globally)");
} }
Save(); if (ImGui.Button("Exclude current character"))
{
_configuration.ExcludedCharacters.Add(new Configuration.CharacterInfo
{
LocalContentId = _clientState.LocalContentId,
CachedPlayerName = _clientState.LocalPlayer?.Name.ToString() ?? "??",
CachedWorldName = worldName,
});
Save();
}
}
ImGui.Unindent(30);
}
else
{
ImGui.TextColored(ImGuiColors.DalamudRed, "You are not logged in.");
}
ImGui.Separator();
ImGui.TextWrapped(
"Characters that won't run auto-cleanup after ventures (/discardall works for excluded characters)");
ImGui.Spacing();
ImGui.Indent(30);
if (_configuration.ExcludedCharacters.Count == 0)
{
ImGui.TextColored(ImGuiColors.DalamudGrey, "No excluded characters.");
}
else
{
foreach (var characterInfo in _configuration.ExcludedCharacters)
{
ImGui.Text(
$"{characterInfo.CachedPlayerName} @ {characterInfo.CachedWorldName} ({characterInfo.LocalContentId:X})");
} }
} }
ImGui.Unindent(30);
ImGui.EndTabItem();
} }
ImGui.EndChild();
ImGui.SameLine();
if (ImGui.BeginChild("Right", new Vector2(-1, -1), true, ImGuiWindowFlags.NoSavedSettings))
{
ImGui.Text("Items that will be automatically discarded");
ImGui.Separator();
List<(uint, string)> toRemove = new();
foreach (var (id, name) in _discarding.OrderBy(x => x.Name.ToLower()))
{
if (ImGui.Selectable(name, true))
toRemove.Add((id, name));
}
if (toRemove.Count > 0)
{
foreach (var tr in toRemove)
_discarding.Remove(tr);
Save();
}
}
ImGui.EndChild();
} }
private void UpdateResults() private void UpdateResults()

View File

@ -8,4 +8,12 @@ public class Configuration : IPluginConfiguration
public int Version { get; set; } = 1; public int Version { get; set; } = 1;
public bool RunAfterVenture { get; set; } public bool RunAfterVenture { get; set; }
public List<uint> DiscardingItems { get; set; } = new(); public List<uint> DiscardingItems { get; set; } = new();
public List<CharacterInfo> ExcludedCharacters { get; set; } = new();
public class CharacterInfo
{
public ulong LocalContentId { get; set; }
public string CachedPlayerName { get; set; }
public string CachedWorldName { get; set; }
}
} }

View File

@ -36,16 +36,24 @@ public class InventoryUtils : IDisposable
foreach (InventoryType inventoryType in InventoryTypes) foreach (InventoryType inventoryType in InventoryTypes)
{ {
InventoryContainer* container = inventoryManager->GetInventoryContainer(inventoryType); InventoryContainer* container = inventoryManager->GetInventoryContainer(inventoryType);
//PluginLog.Verbose($"Checking {inventoryType}, {container->Size}");
for (int i = 0; i < container->Size; ++i) for (int i = 0; i < container->Size; ++i)
{ {
var item = container->GetInventorySlot(i); var item = container->GetInventorySlot(i);
if (item != null) if (item != null)
{ {
//PluginLog.Verbose($"{i} → {item->ItemID}");
if (_configuration.DiscardingItems.Contains(item->ItemID)) if (_configuration.DiscardingItems.Contains(item->ItemID))
{ {
PluginLog.Information(
$"Found item {item->ItemID} to discard in inventory {inventoryType} in slot {i}");
return item; return item;
} }
} }
else
{
//PluginLog.Verbose($"{i} → none");
}
} }
} }