//
// UseItemOperation.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Diagnostics;
using NosSmooth.Data.Abstractions.Enums;
using NosSmooth.Extensions.Combat.Selectors;
using NosSmooth.Game.Data.Inventory;
using NosSmooth.Game.Extensions;
using NosSmooth.Packets.Client.Inventory;
using Remora.Results;
namespace NosSmooth.Extensions.Combat.Operations;
///
/// A combat operation to use an item.
///
/// The item to use.
public record UseItemOperation(InventoryItem Item) : ICombatOperation
{
private Task? _useItemOperation;
private CancellationTokenSource? _ct;
private bool _disposed;
///
public OperationQueueType QueueType => OperationQueueType.Item;
///
public bool MayBeCancelled => true;
///
public Task BeginExecution(ICombatState combatState, CancellationToken ct = default)
{
if (_useItemOperation is not null)
{
return Task.FromResult(Result.FromSuccess());
}
_ct = new CancellationTokenSource();
_useItemOperation = Task.Run(
() => combatState.Client.SendPacketAsync(new UseItemPacket(Item.Bag.Convert(), Item.Item.Slot), _ct.Token),
_ct.Token
);
return Task.FromResult(Result.FromSuccess());
}
///
public async Task WaitForFinishedAsync(ICombatState combatState, CancellationToken ct = default)
{
if (IsFinished())
{
return Result.FromSuccess();
}
await BeginExecution(combatState, ct);
if (_useItemOperation is null)
{
throw new UnreachableException();
}
try
{
return await _useItemOperation;
}
catch (OperationCanceledException)
{
return Result.FromSuccess();
}
catch (Exception e)
{
return e;
}
}
///
public bool IsExecuting()
=> _useItemOperation is not null && !IsFinished();
///
public bool IsFinished()
=> _useItemOperation?.IsCompleted ?? false;
///
public Result CanBeUsed(ICombatState combatState)
=> Result.FromSuccess();
///
public void Cancel()
{
_ct?.Cancel();
}
///
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
_ct?.Cancel();
_useItemOperation?.Dispose();
_ct?.Dispose();
}
}