Enable tracking only when there exists a subscriber

This commit is contained in:
Soreepeong 2023-12-02 12:58:55 +09:00
parent 5f0b65a6c4
commit e594d59986
12 changed files with 381 additions and 234 deletions

View file

@ -2,15 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using Dalamud.Configuration.Internal;
using Dalamud.Game.Inventory.InventoryChangeArgsTypes;
using Dalamud.Game.Inventory.InventoryEventArgTypes;
using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Services;
using Serilog.Events;
namespace Dalamud.Game.Inventory;
/// <summary>
@ -18,9 +16,10 @@ namespace Dalamud.Game.Inventory;
/// </summary>
[InterfaceVersion("1.0")]
[ServiceManager.BlockingEarlyLoadedService]
internal class GameInventory : IDisposable, IServiceType, IGameInventory
internal class GameInventory : IDisposable, IServiceType
{
private static readonly ModuleLog Log = new(nameof(GameInventory));
private readonly List<GameInventoryPluginScoped> subscribersPendingChange = new();
private readonly List<GameInventoryPluginScoped> subscribers = new();
private readonly List<InventoryItemAddedArgs> addedEvents = new();
private readonly List<InventoryItemRemovedArgs> removedEvents = new();
@ -32,120 +31,58 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory
[ServiceManager.ServiceDependency]
private readonly Framework framework = Service<Framework>.Get();
[ServiceManager.ServiceDependency]
private readonly DalamudConfiguration dalamudConfiguration = Service<DalamudConfiguration>.Get();
private readonly GameInventoryType[] inventoryTypes;
private readonly GameInventoryItem[]?[] inventoryItems;
private bool subscribersChanged;
[ServiceManager.ServiceConstructor]
private GameInventory()
{
this.inventoryTypes = Enum.GetValues<GameInventoryType>();
this.inventoryItems = new GameInventoryItem[this.inventoryTypes.Length][];
this.framework.Update += this.OnFrameworkUpdate;
// Separate log logic as an event handler.
this.InventoryChanged += events =>
{
if (this.dalamudConfiguration.LogLevel > LogEventLevel.Verbose)
return;
foreach (var e in events)
{
if (e is InventoryComplexEventArgs icea)
Log.Verbose($"{icea}\n\t├ {icea.SourceEvent}\n\t└ {icea.TargetEvent}");
else
Log.Verbose($"{e}");
}
};
}
/// <inheritdoc/>
public event IGameInventory.InventoryChangelogDelegate? InventoryChanged;
/// <inheritdoc/>
public event IGameInventory.InventoryChangelogDelegate? InventoryChangedRaw;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate? ItemAdded;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate? ItemRemoved;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate? ItemChanged;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate? ItemMoved;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate? ItemSplit;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate? ItemMerged;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate<InventoryItemAddedArgs>? ItemAddedExplicit;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate<InventoryItemRemovedArgs>? ItemRemovedExplicit;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate<InventoryItemChangedArgs>? ItemChangedExplicit;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate<InventoryItemMovedArgs>? ItemMovedExplicit;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate<InventoryItemSplitArgs>? ItemSplitExplicit;
/// <inheritdoc/>
public event IGameInventory.InventoryChangedDelegate<InventoryItemMergedArgs>? ItemMergedExplicit;
/// <inheritdoc/>
public void Dispose()
{
lock (this.subscribersPendingChange)
{
this.subscribers.Clear();
this.subscribersPendingChange.Clear();
this.subscribersChanged = false;
this.framework.Update -= this.OnFrameworkUpdate;
}
private static void InvokeSafely(
IGameInventory.InventoryChangelogDelegate? cb,
IReadOnlyCollection<InventoryEventArgs> data)
{
try
{
cb?.Invoke(data);
}
catch (Exception e)
/// <summary>
/// Subscribe to events.
/// </summary>
/// <param name="s">The event target.</param>
public void Subscribe(GameInventoryPluginScoped s)
{
Log.Error(e, "Exception during batch callback");
lock (this.subscribersPendingChange)
{
this.subscribersPendingChange.Add(s);
this.subscribersChanged = true;
if (this.subscribersPendingChange.Count == 1)
this.framework.Update += this.OnFrameworkUpdate;
}
}
private static void InvokeSafely(IGameInventory.InventoryChangedDelegate? cb, InventoryEventArgs arg)
/// <summary>
/// Unsubscribe from events.
/// </summary>
/// <param name="s">The event target.</param>
public void Unsubscribe(GameInventoryPluginScoped s)
{
try
lock (this.subscribersPendingChange)
{
cb?.Invoke(arg.Type, arg);
}
catch (Exception e)
{
Log.Error(e, "Exception during {argType} callback", arg.Type);
}
}
private static void InvokeSafely<T>(IGameInventory.InventoryChangedDelegate<T>? cb, T arg)
where T : InventoryEventArgs
{
try
{
cb?.Invoke(arg);
}
catch (Exception e)
{
Log.Error(e, "Exception during {argType} callback", arg.Type);
if (!this.subscribersPendingChange.Remove(s))
return;
this.subscribersChanged = true;
if (this.subscribersPendingChange.Count == 0)
this.framework.Update -= this.OnFrameworkUpdate;
}
}
@ -193,18 +130,40 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory
if (this.addedEvents.Count == 0 && this.removedEvents.Count == 0 && this.changedEvents.Count == 0)
return;
// Make a copy of subscribers, to accommodate self removal during the loop.
if (this.subscribersChanged)
{
bool isNew;
lock (this.subscribersPendingChange)
{
isNew = this.subscribersPendingChange.Any() && !this.subscribers.Any();
this.subscribers.Clear();
this.subscribers.AddRange(this.subscribersPendingChange);
this.subscribersChanged = false;
}
// Is this the first time (resuming) scanning for changes? Then discard the "changes".
if (isNew)
{
this.addedEvents.Clear();
this.removedEvents.Clear();
this.changedEvents.Clear();
return;
}
}
// Broadcast InventoryChangedRaw.
// Same reason with the above on why are there 3 lists of events involved.
InvokeSafely(
this.InventoryChangedRaw,
new DeferredReadOnlyCollection<InventoryEventArgs>(
var allRawEventsCollection = new DeferredReadOnlyCollection<InventoryEventArgs>(
this.addedEvents.Count +
this.removedEvents.Count +
this.changedEvents.Count,
() => Array.Empty<InventoryEventArgs>()
.Concat(this.addedEvents)
.Concat(this.removedEvents)
.Concat(this.changedEvents)));
.Concat(this.changedEvents));
foreach (var s in this.subscribers)
s.InvokeChangedRaw(allRawEventsCollection);
// Resolve moved items, from 1 added + 1 removed event.
for (var iAdded = this.addedEvents.Count - 1; iAdded >= 0; --iAdded)
@ -291,10 +250,8 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory
}
}
// Broadcast the rest.
InvokeSafely(
this.InventoryChanged,
new DeferredReadOnlyCollection<InventoryEventArgs>(
// Create a collection view of all events.
var allEventsCollection = new DeferredReadOnlyCollection<InventoryEventArgs>(
this.addedEvents.Count +
this.removedEvents.Count +
this.changedEvents.Count +
@ -307,42 +264,18 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory
.Concat(this.changedEvents)
.Concat(this.movedEvents)
.Concat(this.splitEvents)
.Concat(this.mergedEvents)));
.Concat(this.mergedEvents));
foreach (var x in this.addedEvents)
// Broadcast the rest.
foreach (var s in this.subscribers)
{
InvokeSafely(this.ItemAdded, x);
InvokeSafely(this.ItemAddedExplicit, x);
}
foreach (var x in this.removedEvents)
{
InvokeSafely(this.ItemRemoved, x);
InvokeSafely(this.ItemRemovedExplicit, x);
}
foreach (var x in this.changedEvents)
{
InvokeSafely(this.ItemChanged, x);
InvokeSafely(this.ItemChangedExplicit, x);
}
foreach (var x in this.movedEvents)
{
InvokeSafely(this.ItemMoved, x);
InvokeSafely(this.ItemMovedExplicit, x);
}
foreach (var x in this.splitEvents)
{
InvokeSafely(this.ItemSplit, x);
InvokeSafely(this.ItemSplitExplicit, x);
}
foreach (var x in this.mergedEvents)
{
InvokeSafely(this.ItemMerged, x);
InvokeSafely(this.ItemMergedExplicit, x);
s.InvokeChanged(allEventsCollection);
s.Invoke(this.addedEvents);
s.Invoke(this.removedEvents);
s.Invoke(this.changedEvents);
s.Invoke(this.movedEvents);
s.Invoke(this.splitEvents);
s.Invoke(this.mergedEvents);
}
// We're done using the lists. Clean them up.
@ -388,29 +321,15 @@ internal class GameInventory : IDisposable, IServiceType, IGameInventory
#pragma warning restore SA1015
internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInventory
{
private static readonly ModuleLog Log = new(nameof(GameInventoryPluginScoped));
[ServiceManager.ServiceDependency]
private readonly GameInventory gameInventoryService = Service<GameInventory>.Get();
/// <summary>
/// Initializes a new instance of the <see cref="GameInventoryPluginScoped"/> class.
/// </summary>
public GameInventoryPluginScoped()
{
this.gameInventoryService.InventoryChanged += this.OnInventoryChangedForward;
this.gameInventoryService.InventoryChangedRaw += this.OnInventoryChangedRawForward;
this.gameInventoryService.ItemAdded += this.OnInventoryItemAddedForward;
this.gameInventoryService.ItemRemoved += this.OnInventoryItemRemovedForward;
this.gameInventoryService.ItemMoved += this.OnInventoryItemMovedForward;
this.gameInventoryService.ItemChanged += this.OnInventoryItemChangedForward;
this.gameInventoryService.ItemSplit += this.OnInventoryItemSplitForward;
this.gameInventoryService.ItemMerged += this.OnInventoryItemMergedForward;
this.gameInventoryService.ItemAddedExplicit += this.OnInventoryItemAddedExplicitForward;
this.gameInventoryService.ItemRemovedExplicit += this.OnInventoryItemRemovedExplicitForward;
this.gameInventoryService.ItemChangedExplicit += this.OnInventoryItemChangedExplicitForward;
this.gameInventoryService.ItemMovedExplicit += this.OnInventoryItemMovedExplicitForward;
this.gameInventoryService.ItemSplitExplicit += this.OnInventoryItemSplitExplicitForward;
this.gameInventoryService.ItemMergedExplicit += this.OnInventoryItemMergedExplicitForward;
}
public GameInventoryPluginScoped() => this.gameInventoryService.Subscribe(this);
/// <inheritdoc/>
public event IGameInventory.InventoryChangelogDelegate? InventoryChanged;
@ -457,20 +376,7 @@ internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInven
/// <inheritdoc/>
public void Dispose()
{
this.gameInventoryService.InventoryChanged -= this.OnInventoryChangedForward;
this.gameInventoryService.InventoryChangedRaw -= this.OnInventoryChangedRawForward;
this.gameInventoryService.ItemAdded -= this.OnInventoryItemAddedForward;
this.gameInventoryService.ItemRemoved -= this.OnInventoryItemRemovedForward;
this.gameInventoryService.ItemChanged -= this.OnInventoryItemChangedForward;
this.gameInventoryService.ItemMoved -= this.OnInventoryItemMovedForward;
this.gameInventoryService.ItemSplit -= this.OnInventoryItemSplitForward;
this.gameInventoryService.ItemMerged -= this.OnInventoryItemMergedForward;
this.gameInventoryService.ItemAddedExplicit -= this.OnInventoryItemAddedExplicitForward;
this.gameInventoryService.ItemRemovedExplicit -= this.OnInventoryItemRemovedExplicitForward;
this.gameInventoryService.ItemChangedExplicit -= this.OnInventoryItemChangedExplicitForward;
this.gameInventoryService.ItemMovedExplicit -= this.OnInventoryItemMovedExplicitForward;
this.gameInventoryService.ItemSplitExplicit -= this.OnInventoryItemSplitExplicitForward;
this.gameInventoryService.ItemMergedExplicit -= this.OnInventoryItemMergedExplicitForward;
this.gameInventoryService.Unsubscribe(this);
this.InventoryChanged = null;
this.InventoryChangedRaw = null;
@ -488,45 +394,122 @@ internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInven
this.ItemMergedExplicit = null;
}
private void OnInventoryChangedForward(IReadOnlyCollection<InventoryEventArgs> events)
=> this.InventoryChanged?.Invoke(events);
/// <summary>
/// Invoke <see cref="InventoryChanged"/>.
/// </summary>
/// <param name="data">The data.</param>
internal void InvokeChanged(IReadOnlyCollection<InventoryEventArgs> data)
{
try
{
this.InventoryChanged?.Invoke(data);
}
catch (Exception e)
{
Log.Error(
e,
"[{plugin}] Exception during {argType} callback",
Service<PluginManager>.GetNullable()?.FindCallingPlugin(new(e))?.Name ?? "(unknown plugin)",
nameof(this.InventoryChanged));
}
}
private void OnInventoryChangedRawForward(IReadOnlyCollection<InventoryEventArgs> events)
=> this.InventoryChangedRaw?.Invoke(events);
/// <summary>
/// Invoke <see cref="InventoryChangedRaw"/>.
/// </summary>
/// <param name="data">The data.</param>
internal void InvokeChangedRaw(IReadOnlyCollection<InventoryEventArgs> data)
{
try
{
this.InventoryChangedRaw?.Invoke(data);
}
catch (Exception e)
{
Log.Error(
e,
"[{plugin}] Exception during {argType} callback",
Service<PluginManager>.GetNullable()?.FindCallingPlugin(new(e))?.Name ?? "(unknown plugin)",
nameof(this.InventoryChangedRaw));
}
}
private void OnInventoryItemAddedForward(GameInventoryEvent type, InventoryEventArgs data)
=> this.ItemAdded?.Invoke(type, data);
// Note below: using List<T> instead of IEnumerable<T>, since List<T> has a specialized lightweight enumerator.
private void OnInventoryItemRemovedForward(GameInventoryEvent type, InventoryEventArgs data)
=> this.ItemRemoved?.Invoke(type, data);
/// <summary>
/// Invoke the appropriate event handler.
/// </summary>
/// <param name="events">The data.</param>
internal void Invoke(List<InventoryItemAddedArgs> events) =>
Invoke(this.ItemAdded, this.ItemAddedExplicit, events);
private void OnInventoryItemChangedForward(GameInventoryEvent type, InventoryEventArgs data)
=> this.ItemChanged?.Invoke(type, data);
/// <summary>
/// Invoke the appropriate event handler.
/// </summary>
/// <param name="events">The data.</param>
internal void Invoke(List<InventoryItemRemovedArgs> events) =>
Invoke(this.ItemRemoved, this.ItemRemovedExplicit, events);
private void OnInventoryItemMovedForward(GameInventoryEvent type, InventoryEventArgs data)
=> this.ItemMoved?.Invoke(type, data);
/// <summary>
/// Invoke the appropriate event handler.
/// </summary>
/// <param name="events">The data.</param>
internal void Invoke(List<InventoryItemChangedArgs> events) =>
Invoke(this.ItemChanged, this.ItemChangedExplicit, events);
private void OnInventoryItemSplitForward(GameInventoryEvent type, InventoryEventArgs data)
=> this.ItemSplit?.Invoke(type, data);
/// <summary>
/// Invoke the appropriate event handler.
/// </summary>
/// <param name="events">The data.</param>
internal void Invoke(List<InventoryItemMovedArgs> events) =>
Invoke(this.ItemMoved, this.ItemMovedExplicit, events);
private void OnInventoryItemMergedForward(GameInventoryEvent type, InventoryEventArgs data)
=> this.ItemMerged?.Invoke(type, data);
/// <summary>
/// Invoke the appropriate event handler.
/// </summary>
/// <param name="events">The data.</param>
internal void Invoke(List<InventoryItemSplitArgs> events) =>
Invoke(this.ItemSplit, this.ItemSplitExplicit, events);
private void OnInventoryItemAddedExplicitForward(InventoryItemAddedArgs data)
=> this.ItemAddedExplicit?.Invoke(data);
/// <summary>
/// Invoke the appropriate event handler.
/// </summary>
/// <param name="events">The data.</param>
internal void Invoke(List<InventoryItemMergedArgs> events) =>
Invoke(this.ItemMerged, this.ItemMergedExplicit, events);
private void OnInventoryItemRemovedExplicitForward(InventoryItemRemovedArgs data)
=> this.ItemRemovedExplicit?.Invoke(data);
private static void Invoke<T>(
IGameInventory.InventoryChangedDelegate? cb,
IGameInventory.InventoryChangedDelegate<T>? cbt,
List<T> events) where T : InventoryEventArgs
{
foreach (var evt in events)
{
try
{
cb?.Invoke(evt.Type, evt);
}
catch (Exception e)
{
Log.Error(
e,
"[{plugin}] Exception during untyped callback for {evt}",
Service<PluginManager>.GetNullable()?.FindCallingPlugin(new(e))?.Name ?? "(unknown plugin)",
evt);
}
private void OnInventoryItemChangedExplicitForward(InventoryItemChangedArgs data)
=> this.ItemChangedExplicit?.Invoke(data);
private void OnInventoryItemMovedExplicitForward(InventoryItemMovedArgs data)
=> this.ItemMovedExplicit?.Invoke(data);
private void OnInventoryItemSplitExplicitForward(InventoryItemSplitArgs data)
=> this.ItemSplitExplicit?.Invoke(data);
private void OnInventoryItemMergedExplicitForward(InventoryItemMergedArgs data)
=> this.ItemMergedExplicit?.Invoke(data);
try
{
cbt?.Invoke(evt);
}
catch (Exception e)
{
Log.Error(
e,
"[{plugin}] Exception during typed callback for {evt}",
Service<PluginManager>.GetNullable()?.FindCallingPlugin(new(e))?.Name ?? "(unknown plugin)",
evt);
}
}
}
}

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an item being affected across different slots, possibly in different containers.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Abstract base class representing inventory changed events.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an item being added to an inventory.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an items properties being changed.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an item being merged from two stacks into one.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an item being moved from one inventory and added to another.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an item being removed from an inventory.

View file

@ -1,4 +1,4 @@
namespace Dalamud.Game.Inventory.InventoryChangeArgsTypes;
namespace Dalamud.Game.Inventory.InventoryEventArgTypes;
/// <summary>
/// Represents the data associated with an item being split from one stack into two.

View file

@ -33,6 +33,7 @@ internal class DataWindow : Window
new FateTableWidget(),
new FlyTextWidget(),
new FontAwesomeTestWidget(),
new GameInventoryTestWidget(),
new GamepadWidget(),
new GaugeWidget(),
new HookWidget(),

View file

@ -0,0 +1,163 @@
using System.Collections.Generic;
using Dalamud.Configuration.Internal;
using Dalamud.Game.Inventory;
using Dalamud.Game.Inventory.InventoryEventArgTypes;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Logging.Internal;
using ImGuiNET;
using Serilog.Events;
namespace Dalamud.Interface.Internal.Windows.Data;
/// <summary>
/// Tester for <see cref="GameInventory"/>.
/// </summary>
internal class GameInventoryTestWidget : IDataWindowWidget
{
private static readonly ModuleLog Log = new(nameof(GameInventoryTestWidget));
private GameInventoryPluginScoped? scoped;
private bool standardEnabled;
private bool rawEnabled;
/// <inheritdoc/>
public string[]? CommandShortcuts { get; init; } = { "gameinventorytest" };
/// <inheritdoc/>
public string DisplayName { get; init; } = "GameInventory Test";
/// <inheritdoc/>
public bool Ready { get; set; }
/// <inheritdoc/>
public void Load() => this.Ready = true;
/// <inheritdoc/>
public void Draw()
{
if (Service<DalamudConfiguration>.Get().LogLevel > LogEventLevel.Information)
{
ImGuiHelpers.SafeTextColoredWrapped(
ImGuiColors.DalamudRed,
"Enable LogLevel=Information display to see the logs.");
}
using var table = ImRaii.Table(this.DisplayName, 3, ImGuiTableFlags.SizingFixedFit);
if (!table.Success)
return;
ImGui.TableNextColumn();
ImGui.TextUnformatted("Standard Logging");
ImGui.TableNextColumn();
using (ImRaii.Disabled(this.standardEnabled))
{
if (ImGui.Button("Enable##standard-enable") && !this.standardEnabled)
{
this.scoped ??= new();
this.scoped.InventoryChanged += ScopedOnInventoryChanged;
this.standardEnabled = true;
}
}
ImGui.TableNextColumn();
using (ImRaii.Disabled(!this.standardEnabled))
{
if (ImGui.Button("Disable##standard-disable") && this.scoped is not null && this.standardEnabled)
{
this.scoped.InventoryChanged -= ScopedOnInventoryChanged;
this.standardEnabled = false;
if (!this.rawEnabled)
{
this.scoped.Dispose();
this.scoped = null;
}
}
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted("Raw Logging");
ImGui.TableNextColumn();
using (ImRaii.Disabled(this.rawEnabled))
{
if (ImGui.Button("Enable##raw-enable") && !this.rawEnabled)
{
this.scoped ??= new();
this.scoped.InventoryChangedRaw += ScopedOnInventoryChangedRaw;
this.rawEnabled = true;
}
}
ImGui.TableNextColumn();
using (ImRaii.Disabled(!this.rawEnabled))
{
if (ImGui.Button("Disable##raw-disable") && this.scoped is not null && this.rawEnabled)
{
this.scoped.InventoryChangedRaw -= ScopedOnInventoryChangedRaw;
this.rawEnabled = false;
if (!this.standardEnabled)
{
this.scoped.Dispose();
this.scoped = null;
}
}
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted("All");
ImGui.TableNextColumn();
using (ImRaii.Disabled(this.standardEnabled && this.rawEnabled))
{
if (ImGui.Button("Enable##all-enable"))
{
this.scoped ??= new();
if (!this.standardEnabled)
this.scoped.InventoryChanged += ScopedOnInventoryChanged;
if (!this.rawEnabled)
this.scoped.InventoryChangedRaw += ScopedOnInventoryChangedRaw;
this.standardEnabled = this.rawEnabled = true;
}
}
ImGui.TableNextColumn();
using (ImRaii.Disabled(this.scoped is null))
{
if (ImGui.Button("Disable##all-disable"))
{
this.scoped?.Dispose();
this.scoped = null;
this.standardEnabled = this.rawEnabled = false;
}
}
}
private static void ScopedOnInventoryChangedRaw(IReadOnlyCollection<InventoryEventArgs> events)
{
var i = 0;
foreach (var e in events)
Log.Information($"[{++i}/{events.Count}] Raw: {e}");
}
private static void ScopedOnInventoryChanged(IReadOnlyCollection<InventoryEventArgs> events)
{
var i = 0;
foreach (var e in events)
{
if (e is InventoryComplexEventArgs icea)
Log.Information($"[{++i}/{events.Count}] {icea}\n\t├ {icea.SourceEvent}\n\t└ {icea.TargetEvent}");
else
Log.Information($"[{++i}/{events.Count}] {e}");
}
}
}

View file

@ -1,7 +1,7 @@
using System.Collections.Generic;
using Dalamud.Game.Inventory;
using Dalamud.Game.Inventory.InventoryChangeArgsTypes;
using Dalamud.Game.Inventory.InventoryEventArgTypes;
namespace Dalamud.Plugin.Services;