Files
ClassicAssist.Avalonia/ClassicAssist.Shared/Data/Organizer/OrganizerManager.cs
T
Beyhan Oğur d5f52cc3d3 first commit
2026-09-03 04:45:36 +03:00

242 lines
8.0 KiB
C#

using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using ClassicAssist.Shared;
using ClassicAssist.Annotations;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UI.Misc;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Network.PacketFilter;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using UOC = ClassicAssist.Shared.UO.Commands;
namespace ClassicAssist.Data.Organizer
{
public class OrganizerManager : INotifyPropertyChanged
{
private static readonly object _lock = new object();
private static OrganizerManager _instance;
private ObservableCollectionEx<OrganizerEntry> _items = new ObservableCollectionEx<OrganizerEntry>();
private OrganizerManager()
{
Items.CollectionChanged += OnCollectionChanged;
}
public bool IsOrganizing { get; set; }
public ObservableCollectionEx<OrganizerEntry> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
private CancellationTokenSource _cancellationTokenSource { get; set; } = new CancellationTokenSource();
public event PropertyChangedEventHandler PropertyChanged;
private void OnCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
OnPropertyChanged( nameof( Items ) );
}
public async Task Organize( OrganizerEntry entry, int sourceContainer = 0, int destinationContainer = 0 )
{
if ( IsOrganizing )
{
_cancellationTokenSource.Cancel();
return;
}
if ( sourceContainer == 0 )
{
sourceContainer = entry.SourceContainer;
}
if ( destinationContainer == 0 )
{
destinationContainer = entry.DestinationContainer;
}
if ( sourceContainer == 0 || destinationContainer == 0 )
{
await SetContainers( entry );
return;
}
Item sourceContainerItem = Engine.Items.GetItem( sourceContainer );
if ( sourceContainerItem == null )
{
//TODO
UOC.SystemMessage( Strings.Cannot_find_container___ );
return;
}
PacketFilterInfo pfi = new PacketFilterInfo( 0x3C,
new[] { PacketFilterConditions.IntAtPositionCondition( sourceContainerItem.Serial, 19 ) } );
if ( UOC.WaitForIncomingPacket( pfi, 1000,
() => Engine.SendPacketToServer( new UseObject( sourceContainerItem.Serial ) ) ) )
{
await Task.Delay( Options.CurrentOptions.ActionDelayMS );
}
if ( sourceContainerItem.Container == null )
{
//TODO
UOC.SystemMessage( Strings.Cannot_find_container___ );
return;
}
Item destinationContainerItem = Engine.Items.GetItem( destinationContainer );
if ( destinationContainerItem == null )
{
//TODO
UOC.SystemMessage( Strings.Cannot_find_container___ );
return;
}
try
{
_cancellationTokenSource = new CancellationTokenSource();
IsOrganizing = true;
UOC.SystemMessage( string.Format( Strings.Organizer__0__running___, entry.Name ) );
foreach ( OrganizerItem entryItem in entry.Items )
{
Item[] moveItems = sourceContainerItem.Container.SelectEntities( i =>
entryItem.ID == i.ID && ( entryItem.Hue == -1 || i.Hue == entryItem.Hue ) );
if ( moveItems == null )
{
continue;
}
bool limitAmount = entryItem.Amount != -1;
int moveAmount = entryItem.Amount;
int moved = 0;
if ( entry.Complete )
{
int existingCount = destinationContainerItem.Container
?.SelectEntities( i =>
entryItem.ID == i.ID &&
( entryItem.Hue == -1 || i.Hue == entryItem.Hue ) )
?.Select( i => i.Count ).Sum() ?? 0;
moved += existingCount;
}
foreach ( Item moveItem in moveItems )
{
if ( limitAmount && moved >= moveAmount )
{
break;
}
int amount = moveItem.Count;
if ( limitAmount )
{
if ( moveItem.Count > moveAmount )
{
amount = moveAmount - moved;
}
moved += amount;
}
if ( entry.Stack )
{
await ActionPacketQueue.EnqueueDragDrop( moveItem.Serial, amount,
destinationContainerItem.Serial );
}
else
{
await ActionPacketQueue.EnqueueDragDrop( moveItem.Serial, amount,
destinationContainerItem.Serial, x: 0, y: 0 );
}
if ( _cancellationTokenSource.IsCancellationRequested )
{
break;
}
}
}
}
finally
{
UOC.SystemMessage( string.Format( Strings.Organizer__0__finished___, entry.Name ) );
IsOrganizing = false;
}
}
public async Task SetContainers( object obj )
{
if ( !( obj is OrganizerEntry entry ) )
{
return;
}
int sourceContainer = await UOC.GetTargeSerialAsync( Strings.Select_source_container___ );
if ( sourceContainer <= 0 )
{
UOC.SystemMessage( Strings.Invalid_source_container___ );
return;
}
int desintationContainer = await UOC.GetTargeSerialAsync( Strings.Select_destination_container___ );
if ( desintationContainer <= 0 )
{
UOC.SystemMessage( Strings.Invalid_destination_container___ );
return;
}
entry.SourceContainer = sourceContainer;
entry.DestinationContainer = desintationContainer;
UOC.SystemMessage( Strings.Organizer_containers_set___ );
}
public static OrganizerManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _lock )
{
if ( _instance != null )
{
return _instance;
}
_instance = new OrganizerManager();
return _instance;
}
}
return _instance;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
public void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
}
}
}