using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using ClassicAssist.Data; using ClassicAssist.Data.Dress; using ClassicAssist.Data.Hotkeys; using ClassicAssist.Misc; using ClassicAssist.Shared.Resources; using ClassicAssist.Shared.UO; using ClassicAssist.UI.ViewModels; using ClassicAssist.UO.Data; using ClassicAssist.UO.Objects; using Newtonsoft.Json.Linq; using ReactiveUI; namespace ClassicAssist.Shared.UI.ViewModels.Agents { public class DressTabViewModel : HotkeyEntryViewModel, ISettingProvider { private readonly IObservable _entrySelected; private readonly DressManager _manager; private readonly Layer[] _validLayers = { Layer.Arms, Layer.Bracelet, Layer.Cloak, Layer.Earrings, Layer.Gloves, Layer.Helm, Layer.InnerLegs, Layer.InnerTorso, Layer.MiddleTorso, Layer.Neck, Layer.OneHanded, Layer.OuterLegs, Layer.OuterTorso, Layer.Pants, Layer.Ring, Layer.Shirt, Layer.Shoes, Layer.Talisman, Layer.TwoHanded, Layer.Waist }; private ICommand _addDressItemCommand; private ICommand _changeDressType; private ICommand _clearDressItemsCommand; private ICommand _dressAllItemsCommand; private ICommand _importItemsCommand; private bool _isDressingOrUndressing; private readonly IObservable _itemSelected; private bool _moveConflictingItems; private ICommand _newDressEntryCommand; private ICommand _removeDressEntryCommand; private ICommand _removeDressItemCommand; private DressAgentItem _selectedDressItem; private DressAgentEntry _selectedItem; private ICommand _setUndressContainerCommand; private ICommand _undressAllItemsCommand; private ICommand _undressItemsCommand; private bool _useUo3DPackets; public DressTabViewModel() : base( Strings.Dress ) { _manager = DressManager.GetInstance(); _manager.Items = Items; _entrySelected = this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ); _itemSelected = this.WhenAnyValue( e => e.SelectedDressItem, selector: e => e != null ); } public ICommand AddDressItemCommand => _addDressItemCommand ?? ( _addDressItemCommand = new RelayCommandAsync( AddDressItem, o => true ) ); //TODO UI public ICommand ChangeDressTypeCommand => _changeDressType ?? ( _changeDressType = new RelayCommand( ChangeDressType, o => SelectedDressItem != null ) ); public ICommand ClearDressItemsCommand => _clearDressItemsCommand ?? ( _clearDressItemsCommand = ReactiveCommand.Create( ClearDressItems, _entrySelected ) ); public ICommand DressAllItemsCommand => _dressAllItemsCommand ?? ( _dressAllItemsCommand = ReactiveCommand.CreateFromTask( DressAllItems, _entrySelected.Merge( this.WhenAnyValue( e => e.IsDressingOrUndressing, e => !e ) ) ) ); public ICommand ImportItemsCommand => _importItemsCommand ?? ( _importItemsCommand = ReactiveCommand.Create( ImportItems, _entrySelected ) ); public bool IsDressingOrUndressing { get => _isDressingOrUndressing; set => SetProperty( ref _isDressingOrUndressing, value ); } public bool MoveConflictingItems { get => _moveConflictingItems; set => SetProperty( ref _moveConflictingItems, value ); } public ICommand NewDressEntryCommand => _newDressEntryCommand ?? ( _newDressEntryCommand = new RelayCommand( NewDressEntry, o => true ) ); public ICommand RemoveDressEntryCommand => _removeDressEntryCommand ?? ( _removeDressEntryCommand = ReactiveCommand.Create( RemoveDressEntry, _entrySelected ) ); public ICommand RemoveDressItemCommand => _removeDressItemCommand ?? ( _removeDressItemCommand = ReactiveCommand.Create( RemoveDressItem, _itemSelected ) ); public DressAgentItem SelectedDressItem { get => _selectedDressItem; set => SetProperty( ref _selectedDressItem, value ); } public DressAgentEntry SelectedItem { get => _selectedItem; set => SetProperty( ref _selectedItem, value ); } public ICommand SetUndressContainerCommand => _setUndressContainerCommand ?? ( _setUndressContainerCommand = ReactiveCommand.CreateFromTask( SetUndressContainer, _entrySelected ) ); public ICommand UndressAllItemsCommand => _undressAllItemsCommand ?? ( _undressAllItemsCommand = ReactiveCommand.CreateFromTask( UndressAllItems, this.WhenAnyValue( e => e.IsDressingOrUndressing, e => !e ) ) ); public ICommand UndressItemsCommand => _undressItemsCommand ?? ( _undressItemsCommand = ReactiveCommand.CreateFromTask( UndressItems, this.WhenAnyValue( e => e.IsDressingOrUndressing, e => !e ) ) ); public bool UseUO3DPackets { get => _useUo3DPackets; set { SetProperty( ref _useUo3DPackets, value ); if ( _manager != null ) { _manager.UseUO3DPackets = value; } } } public void Serialize( JObject json ) { JObject dress = new JObject { { "Options", new JObject { ["MoveConflictingItems"] = MoveConflictingItems, ["UseUO3DPackets"] = UseUO3DPackets } } }; JArray dressEntries = new JArray(); foreach ( DressAgentEntry dae in Items ) { JObject djson = new JObject(); SetJsonValue( djson, "Name", dae.Name ); SetJsonValue( djson, "UndressContainer", dae.UndressContainer ); SetJsonValue( djson, "PassToUO", dae.PassToUO ); SetJsonValue( djson, "Keys", dae.Hotkey.ToJObject() ); JArray items = new JArray(); if ( dae.Items != null ) { foreach ( DressAgentItem dressAgentItem in dae.Items ) { JObject item = new JObject { { "Layer", (int) dressAgentItem.Layer }, { "Serial", dressAgentItem.Serial }, { "ID", dressAgentItem.ID }, { "Type", (int) dressAgentItem.Type } }; items.Add( item ); } } djson.Add( "Items", items ); dressEntries.Add( djson ); } dress.Add( "Entries", dressEntries ); json?.Add( "Dress", dress ); } public void Deserialize( JObject json, Options options ) { Items.Clear(); if ( json?["Dress"] == null ) { return; } JToken dress = json["Dress"]; MoveConflictingItems = GetJsonValue( dress["Options"], "MoveConflictingItems", false ); UseUO3DPackets = _manager.UseUO3DPackets = GetJsonValue( dress["Options"], "UseUO3DPackets", false ); foreach ( JToken entry in dress["Entries"] ) { DressAgentEntry dae = new DressAgentEntry { Name = GetJsonValue( entry, "Name", string.Empty ), UndressContainer = GetJsonValue( entry, "UndressContainer", 0 ), PassToUO = GetJsonValue( entry, "PassToUO", true ), Hotkey = new ShortcutKeys( entry["Keys"] ) }; dae.Action = async hks => await DressAllItems( dae ); List items = new List(); if ( entry["Items"] != null ) { items.AddRange( entry["Items"].Select( itemEntry => new DressAgentItem { Layer = GetJsonValue( itemEntry, "Layer", Layer.Invalid ), Serial = GetJsonValue( itemEntry, "Serial", 0 ), ID = GetJsonValue( itemEntry, "ID", -1 ), Type = GetJsonValue( itemEntry, "Type", DressAgentItemType.Serial ) } ) ); } dae.Items = new List( items ); Items.Add( dae ); } } private async Task UndressItems( object arg ) { if ( !( arg is DressAgentEntry dae ) ) { return; } try { IsDressingOrUndressing = true; await dae.Undress(); } finally { IsDressingOrUndressing = false; } } private static async Task SetUndressContainer( object obj ) { if ( !( obj is DressAgentEntry entry ) ) { return; } int serial = await Commands.GetTargeSerialAsync( Strings.Select_undress_container___ ); if ( serial <= 0 ) { Commands.SystemMessage( Strings.Invalid_container___ ); return; } entry.UndressContainer = serial; } private static void ClearDressItems( object obj ) { if ( !( obj is DressAgentEntry dae ) ) { return; } dae.Items = new List(); } private void RemoveDressItem( object obj ) { if ( !( obj is DressAgentItem removeItem ) ) { return; } if ( !SelectedItem.Items.Contains( removeItem ) ) { return; } List list = SelectedItem.Items.ToList(); list.Remove( removeItem ); SelectedItem.Items = list; } private static async Task AddDressItem( object arg ) { if ( !( arg is DressAgentEntry dae ) ) { return; } int serial = await Commands.GetTargeSerialAsync( Strings.Target_clothing_item___ ); Item item = Engine.Items.GetItem( serial ); if ( item == null ) { Commands.SystemMessage( Strings.Cannot_find_item___ ); return; } if ( item.Layer == Layer.Invalid ) { Commands.SystemMessage( Strings.The_item_needs_to_be_equipped___ ); return; } dae.AddOrReplaceDressItem( item ); } private async Task UndressAllItems( CancellationToken cancellationToken ) { IsDressingOrUndressing = true; await _manager.UndressAll( cancellationToken ); IsDressingOrUndressing = false; } private void NewDressEntry( object obj ) { int count = Items.Count; DressAgentEntry dae = new DressAgentEntry { Name = $"Dress-{count + 1}", Items = new List() }; dae.Action = async hks => await DressAllItems( dae ); Items.Add( dae ); } private void RemoveDressEntry( object obj ) { if ( !( obj is DressAgentEntry dae ) ) { return; } dae.Hotkey = ShortcutKeys.Default; Items.Remove( dae ); } private async Task DressAllItems( object obj ) { if ( !( obj is DressAgentEntry dae ) ) { return; } IsDressingOrUndressing = true; await _manager.DressAllItems( dae, MoveConflictingItems ); IsDressingOrUndressing = false; } private void ImportItems( object obj ) { if ( !( obj is DressAgentEntry dae ) ) { return; } _manager.ImportItems( dae ); } public bool IsValidLayer( Layer layer ) { return _validLayers.Any( l => l == layer ); } private static void ChangeDressType( object obj ) { if ( !( obj is DressAgentItem dai ) ) { return; } dai.Type = dai.Type == DressAgentItemType.Serial ? DressAgentItemType.ID : DressAgentItemType.Serial; } } }