first commit
This commit is contained in:
@@ -0,0 +1,597 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Autoloot;
|
||||
using ClassicAssist.Data.Regions;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.Shared.UI.ViewModels.Autoloot;
|
||||
using ClassicAssist.UI.Misc;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
using ClassicAssist.UO.Data;
|
||||
using ClassicAssist.UO.Network;
|
||||
using ClassicAssist.UO.Network.PacketFilter;
|
||||
using ClassicAssist.UO.Network.Packets;
|
||||
using ClassicAssist.UO.Objects;
|
||||
using Microsoft.Scripting.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ReactiveUI;
|
||||
using UOC = ClassicAssist.Shared.UO.Commands;
|
||||
|
||||
namespace ClassicAssist.Shared.UI.ViewModels.Agents
|
||||
{
|
||||
public class AutolootViewModel : BaseViewModel, ISettingProvider
|
||||
{
|
||||
private const int LOOT_TIMEOUT = 5000;
|
||||
private readonly object _autolootLock = new object();
|
||||
private readonly IObservable<bool> _entrySelected;
|
||||
private readonly IObservable<bool> _itemSelected;
|
||||
|
||||
private readonly string _propertiesFile = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory,
|
||||
"Data", "Properties.json" );
|
||||
|
||||
private readonly string _propertiesFileCustom =
|
||||
Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Data", "Properties.Custom.json" );
|
||||
|
||||
private ICommand _clipboardCopyCommand;
|
||||
private ICommand _clipboardPasteCommand;
|
||||
|
||||
private ObservableCollection<PropertyEntry> _constraints = new ObservableCollection<PropertyEntry>();
|
||||
|
||||
private int _containerSerial;
|
||||
private ICommand _defineCustomPropertiesCommand;
|
||||
|
||||
private bool _disableInGuardzone;
|
||||
private bool _enabled;
|
||||
|
||||
private ICommand _insertCommand;
|
||||
private ICommand _insertConstraintCommand;
|
||||
private ICommand _insertMatchAnyCommand;
|
||||
|
||||
private ObservableCollectionEx<AutolootEntry> _items = new ObservableCollectionEx<AutolootEntry>();
|
||||
|
||||
private ICommand _removeCommand;
|
||||
private ICommand _removeConstraintCommand;
|
||||
private ICommand _removeSingleConstraintCommand;
|
||||
private RelayCommand _resetContainerCommand;
|
||||
private AutolootEntry _selectedItem;
|
||||
|
||||
private ObservableCollection<AutolootConstraintEntry> _selectedProperties =
|
||||
new ObservableCollection<AutolootConstraintEntry>();
|
||||
|
||||
private AutolootConstraintEntry _selectedProperty;
|
||||
private ICommand _selectHueCommand;
|
||||
private ICommand _setContainerCommand;
|
||||
|
||||
public AutolootViewModel()
|
||||
{
|
||||
if ( !File.Exists( _propertiesFile ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LoadProperties();
|
||||
LoadCustomProperties();
|
||||
|
||||
AutolootHelpers.SetAutolootContainer = serial => ContainerSerial = serial;
|
||||
IncomingPacketHandlers.CorpseContainerDisplayEvent += OnCorpseEvent;
|
||||
AutolootManager.GetInstance().GetEntries = () => _items.ToList();
|
||||
|
||||
_entrySelected = this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null );
|
||||
_itemSelected = this.WhenAnyValue( e => e.SelectedProperty, selector: e => e != null );
|
||||
}
|
||||
|
||||
public ICommand ClipboardCopyCommand =>
|
||||
_clipboardCopyCommand ?? ( _clipboardCopyCommand = new RelayCommand( ClipboardCopy, o => true ) );
|
||||
|
||||
public ICommand ClipboardPasteCommand =>
|
||||
_clipboardPasteCommand ?? ( _clipboardPasteCommand = new RelayCommand( ClipboardPaste, o => true ) );
|
||||
|
||||
public ObservableCollection<PropertyEntry> Constraints
|
||||
{
|
||||
get => _constraints;
|
||||
set => SetProperty( ref _constraints, value );
|
||||
}
|
||||
|
||||
public int ContainerSerial
|
||||
{
|
||||
get => _containerSerial;
|
||||
set => SetProperty( ref _containerSerial, value );
|
||||
}
|
||||
|
||||
public ICommand DefineCustomPropertiesCommand =>
|
||||
_defineCustomPropertiesCommand ??
|
||||
( _defineCustomPropertiesCommand = new RelayCommand( DefineCustomProperties, o => true ) );
|
||||
|
||||
public bool DisableInGuardzone
|
||||
{
|
||||
get => _disableInGuardzone;
|
||||
set => SetProperty( ref _disableInGuardzone, value );
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set => SetProperty( ref _enabled, value );
|
||||
}
|
||||
|
||||
public ICommand InsertCommand =>
|
||||
_insertCommand ?? ( _insertCommand = ReactiveCommand.CreateFromTask( Insert ) );
|
||||
|
||||
public ICommand InsertConstraintCommand =>
|
||||
_insertConstraintCommand ?? ( _insertConstraintCommand =
|
||||
ReactiveCommand.Create<PropertyEntry>( InsertConstraint, _entrySelected ) );
|
||||
|
||||
public ICommand InsertMatchAnyCommand =>
|
||||
_insertMatchAnyCommand ?? ( _insertMatchAnyCommand = new RelayCommand( InsertMatchAny, o => true ) );
|
||||
|
||||
public ObservableCollectionEx<AutolootEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand RemoveCommand =>
|
||||
_removeCommand ??
|
||||
( _removeCommand = ReactiveCommand.CreateFromTask<AutolootEntry>( Remove, _entrySelected ) );
|
||||
|
||||
public ICommand RemoveConstraintCommand =>
|
||||
_removeConstraintCommand ?? ( _removeConstraintCommand =
|
||||
ReactiveCommand.Create<IEnumerable<AutolootConstraintEntry>>( RemoveConstraint, _itemSelected ) );
|
||||
|
||||
public ICommand RemoveSingleConstraintCommand =>
|
||||
_removeSingleConstraintCommand ?? ( _removeSingleConstraintCommand =
|
||||
ReactiveCommand.Create<AutolootConstraintEntry>( RemoveSingleConstraint, _itemSelected ) );
|
||||
|
||||
public ICommand ResetContainerCommand => _resetContainerCommand = new RelayCommand( ResetContainer, o => true );
|
||||
|
||||
public AutolootEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<AutolootConstraintEntry> SelectedProperties
|
||||
{
|
||||
get => _selectedProperties;
|
||||
set => SetProperty( ref _selectedProperties, value );
|
||||
}
|
||||
|
||||
public AutolootConstraintEntry SelectedProperty
|
||||
{
|
||||
get => _selectedProperty;
|
||||
set => SetProperty( ref _selectedProperty, value );
|
||||
}
|
||||
|
||||
public ICommand SelectHueCommand =>
|
||||
_selectHueCommand ?? ( _selectHueCommand =
|
||||
ReactiveCommand.CreateFromTask<AutolootEntry>( SelectHue, _entrySelected ) );
|
||||
|
||||
public ICommand SetContainerCommand =>
|
||||
_setContainerCommand ?? ( _setContainerCommand = new RelayCommandAsync( SetContainer, o => true ) );
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
if ( json == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JObject autolootObj = new JObject
|
||||
{
|
||||
{ "Enabled", Enabled },
|
||||
{ "DisableInGuardzone", DisableInGuardzone },
|
||||
{ "Container", ContainerSerial }
|
||||
};
|
||||
|
||||
JArray itemsArray = new JArray();
|
||||
|
||||
foreach ( AutolootEntry entry in Items )
|
||||
{
|
||||
JObject entryObj = new JObject
|
||||
{
|
||||
{ "Name", entry.Name },
|
||||
{ "ID", entry.ID },
|
||||
{ "Autoloot", entry.Autoloot },
|
||||
{ "Rehue", entry.Rehue },
|
||||
{ "RehueHue", entry.RehueHue },
|
||||
{ "Enabled", entry.Enabled }
|
||||
};
|
||||
|
||||
if ( entry.Constraints != null )
|
||||
{
|
||||
JArray constraintsArray = new JArray();
|
||||
|
||||
foreach ( AutolootConstraintEntry constraint in entry.Constraints )
|
||||
{
|
||||
JObject constraintObj = new JObject
|
||||
{
|
||||
{ "Name", constraint.Property.Name },
|
||||
{ "Operator", constraint.Operator.ToString() },
|
||||
{ "Value", constraint.Value }
|
||||
};
|
||||
|
||||
constraintsArray.Add( constraintObj );
|
||||
}
|
||||
|
||||
entryObj.Add( "Properties", constraintsArray );
|
||||
}
|
||||
|
||||
itemsArray.Add( entryObj );
|
||||
}
|
||||
|
||||
autolootObj.Add( "Items", itemsArray );
|
||||
|
||||
json.Add( "Autoloot", autolootObj );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Items.Clear();
|
||||
|
||||
if ( json?["Autoloot"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JToken config = json["Autoloot"];
|
||||
|
||||
Enabled = config["Enabled"]?.ToObject<bool>() ?? true;
|
||||
DisableInGuardzone = config["DisableInGuardzone"]?.ToObject<bool>() ?? false;
|
||||
ContainerSerial = config["Container"]?.ToObject<int>() ?? 0;
|
||||
|
||||
if ( config["Items"] != null )
|
||||
{
|
||||
JToken items = config["Items"];
|
||||
|
||||
foreach ( JToken token in items )
|
||||
{
|
||||
AutolootEntry entry = new AutolootEntry
|
||||
{
|
||||
Name = token["Name"]?.ToObject<string>() ?? "Unknown",
|
||||
ID = token["ID"]?.ToObject<int>() ?? 0,
|
||||
Autoloot = token["Autoloot"]?.ToObject<bool>() ?? false,
|
||||
Rehue = token["Rehue"]?.ToObject<bool>() ?? false,
|
||||
RehueHue = token["RehueHue"]?.ToObject<int>() ?? 0,
|
||||
Enabled = token["Enabled"]?.ToObject<bool>() ?? true
|
||||
};
|
||||
|
||||
if ( token["Properties"] != null )
|
||||
{
|
||||
List<AutolootConstraintEntry> constraintsList = new List<AutolootConstraintEntry>();
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach ( JToken constraintToken in token["Properties"] )
|
||||
{
|
||||
string constraintName = constraintToken["Name"]?.ToObject<string>() ?? "Unknown";
|
||||
|
||||
PropertyEntry propertyEntry = Constraints.FirstOrDefault( c => c.Name == constraintName );
|
||||
|
||||
if ( propertyEntry == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AutolootConstraintEntry constraintObj = new AutolootConstraintEntry
|
||||
{
|
||||
Property = propertyEntry,
|
||||
Operator = constraintToken["Operator"]?.ToObject<AutolootOperator>() ??
|
||||
AutolootOperator.Equal,
|
||||
Value = constraintToken["Value"]?.ToObject<int>() ?? 0
|
||||
};
|
||||
|
||||
constraintsList.Add( constraintObj );
|
||||
}
|
||||
|
||||
entry.Constraints.AddRange( constraintsList );
|
||||
}
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveSingleConstraint( AutolootConstraintEntry obj )
|
||||
{
|
||||
SelectedItem?.Constraints.Remove( obj );
|
||||
}
|
||||
|
||||
private void LoadCustomProperties()
|
||||
{
|
||||
if ( !File.Exists( _propertiesFileCustom ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
|
||||
using ( StreamReader sr = new StreamReader( _propertiesFileCustom ) )
|
||||
{
|
||||
using ( JsonTextReader reader = new JsonTextReader( sr ) )
|
||||
{
|
||||
PropertyEntry[] constraints = serializer.Deserialize<PropertyEntry[]>( reader );
|
||||
|
||||
foreach ( PropertyEntry constraint in constraints )
|
||||
{
|
||||
Constraints.AddSorted( constraint );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadProperties()
|
||||
{
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
|
||||
using ( StreamReader sr = new StreamReader( _propertiesFile ) )
|
||||
{
|
||||
using ( JsonTextReader reader = new JsonTextReader( sr ) )
|
||||
{
|
||||
PropertyEntry[] constraints = serializer.Deserialize<PropertyEntry[]>( reader );
|
||||
|
||||
foreach ( PropertyEntry constraint in constraints )
|
||||
{
|
||||
Constraints.AddSorted( constraint );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClipboardPaste( object obj )
|
||||
{
|
||||
string text = Engine.UIInvoker.GetClipboardText();
|
||||
|
||||
try
|
||||
{
|
||||
IEnumerable<AutolootConstraintEntry> entries =
|
||||
JsonConvert.DeserializeObject<IEnumerable<AutolootConstraintEntry>>( text );
|
||||
|
||||
if ( entries == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( AutolootConstraintEntry entry in entries )
|
||||
{
|
||||
if ( !SelectedItem.Constraints.Contains( entry ) )
|
||||
{
|
||||
SelectedItem?.Constraints.Add( entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception )
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClipboardCopy( object obj )
|
||||
{
|
||||
if ( !( obj is IList<AutolootConstraintEntry> entries ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string text = JsonConvert.SerializeObject( entries );
|
||||
|
||||
Engine.UIInvoker.SetClipboardText( text );
|
||||
}
|
||||
|
||||
public void OnCorpseEvent( int serial )
|
||||
{
|
||||
if ( !Enabled )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock ( _autolootLock )
|
||||
{
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null || item.ID != 0x2006 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PacketWaitEntry we = Engine.PacketWaitEntries.Add(
|
||||
new PacketFilterInfo( 0x3C, new[] { PacketFilterConditions.IntAtPositionCondition( serial, 19 ) } ),
|
||||
PacketDirection.Incoming );
|
||||
|
||||
we.Lock.WaitOne( 2000 );
|
||||
|
||||
IEnumerable<Item> items = Engine.Items.GetItem( serial )?.Container?.GetItems();
|
||||
|
||||
if ( items == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Engine.Features.HasFlag( FeatureFlags.AOS ) )
|
||||
{
|
||||
Engine.SendPacketToServer( new BatchQueryProperties( items.Select( i => i.Serial ).ToArray() ) );
|
||||
Thread.Sleep( 1000 );
|
||||
}
|
||||
|
||||
List<Item> lootItems = new List<Item>();
|
||||
|
||||
// If change logic, also change in DebugAutolootViewModel
|
||||
|
||||
foreach ( AutolootEntry entry in Items )
|
||||
{
|
||||
if ( !entry.Enabled )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IEnumerable<Item> matchItems = AutolootHelpers.AutolootFilter( items, entry );
|
||||
|
||||
if ( matchItems == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( Item matchItem in matchItems )
|
||||
{
|
||||
if ( entry.Rehue )
|
||||
{
|
||||
Engine.SendPacketToClient( new ContainerContentUpdate( matchItem.Serial, matchItem.ID,
|
||||
matchItem.Direction, matchItem.Count, matchItem.X, matchItem.Y, matchItem.Grid,
|
||||
matchItem.Owner, entry.RehueHue ) );
|
||||
}
|
||||
|
||||
if ( DisableInGuardzone &&
|
||||
Engine.Player.GetRegion().Attributes.HasFlag( RegionAttributes.Guarded ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( entry.Autoloot )
|
||||
{
|
||||
lootItems.Add( matchItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( Item lootItem in lootItems.Distinct() )
|
||||
{
|
||||
int containerSerial = ContainerSerial;
|
||||
|
||||
if ( containerSerial == 0 || Engine.Items.GetItem( containerSerial ) == null )
|
||||
{
|
||||
containerSerial = Engine.Player.GetLayer( Layer.Backpack );
|
||||
}
|
||||
|
||||
UOC.SystemMessage( string.Format( Strings.Autolooting___0__, lootItem.Name ), 61 );
|
||||
Task t = ActionPacketQueue.EnqueueDragDrop( lootItem.Serial, lootItem.Count, containerSerial,
|
||||
QueuePriority.Medium, true, true );
|
||||
|
||||
t.Wait( LOOT_TIMEOUT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveConstraint( object obj )
|
||||
{
|
||||
if ( !( obj is IEnumerable<AutolootConstraintEntry> constraints ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( AutolootConstraintEntry constraintEntry in constraints.ToList() )
|
||||
{
|
||||
SelectedItem?.Constraints.Remove( constraintEntry );
|
||||
}
|
||||
}
|
||||
|
||||
private void InsertConstraint( object obj )
|
||||
{
|
||||
if ( !( obj is PropertyEntry propertyEntry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<AutolootConstraintEntry> constraints =
|
||||
new List<AutolootConstraintEntry>( SelectedItem.Constraints )
|
||||
{
|
||||
new AutolootConstraintEntry { Property = propertyEntry }
|
||||
};
|
||||
|
||||
SelectedItem.Constraints = new ObservableCollection<AutolootConstraintEntry>( constraints );
|
||||
}
|
||||
|
||||
private void DefineCustomProperties( object obj )
|
||||
{
|
||||
Engine.UIInvoker.InvokeDialog<CustomPropertiesViewModel>( "CustomPropertiesWindow" );
|
||||
Constraints.Clear();
|
||||
LoadProperties();
|
||||
LoadCustomProperties();
|
||||
}
|
||||
|
||||
private void ResetContainer( object obj )
|
||||
{
|
||||
ContainerSerial = 0;
|
||||
}
|
||||
|
||||
private async Task SetContainer( object arg )
|
||||
{
|
||||
int serial = await UOC.GetTargeSerialAsync( Strings.Target_container___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerSerial = serial;
|
||||
}
|
||||
|
||||
private void InsertMatchAny( object obj )
|
||||
{
|
||||
AutolootEntry entry = new AutolootEntry
|
||||
{
|
||||
Name = Strings.Any, ID = -1, Constraints = new ObservableCollection<AutolootConstraintEntry>()
|
||||
};
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
|
||||
private async Task Insert( CancellationToken cancellationToken )
|
||||
{
|
||||
int serial = await UOC.GetTargeSerialAsync( Strings.Target_object___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
AutolootEntry entry = new AutolootEntry
|
||||
{
|
||||
Name = TileData.GetStaticTile( item.ID ).Name,
|
||||
ID = item.ID,
|
||||
Constraints = new ObservableCollection<AutolootConstraintEntry>()
|
||||
};
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
|
||||
private async Task Remove( object arg )
|
||||
{
|
||||
if ( !( arg is AutolootEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static async Task SelectHue( object obj )
|
||||
{
|
||||
if ( !( obj is AutolootEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int hue = await Engine.UIInvoker.GetHueAsync();
|
||||
|
||||
entry.RehueHue = hue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Counters;
|
||||
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 CountersTabViewModel : BaseViewModel, ISettingProvider
|
||||
{
|
||||
private ICommand _insertEntryCommand;
|
||||
private ObservableCollection<CountersAgentEntry> _items = new ObservableCollection<CountersAgentEntry>();
|
||||
private ICommand _recountCommand;
|
||||
private ICommand _removeEntryCommand;
|
||||
private CountersAgentEntry _selectedItem;
|
||||
private bool _warn = true;
|
||||
private int _warnAmount;
|
||||
|
||||
public CountersTabViewModel()
|
||||
{
|
||||
CountersManager manager = CountersManager.GetInstance();
|
||||
|
||||
manager.Items = Items;
|
||||
manager.RecountAll = Recount;
|
||||
}
|
||||
|
||||
public ICommand InsertEntryCommand =>
|
||||
_insertEntryCommand ?? ( _insertEntryCommand = new RelayCommandAsync( InsertEntry, o => true ) );
|
||||
|
||||
public ObservableCollection<CountersAgentEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand RecountCommand => _recountCommand ?? ( _recountCommand = ReactiveCommand.Create( Recount ) );
|
||||
|
||||
public ICommand RemoveEntryCommand =>
|
||||
_removeEntryCommand ?? ( _removeEntryCommand = ReactiveCommand.Create<CountersAgentEntry>( RemoveEntry,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
|
||||
public CountersAgentEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public bool Warn
|
||||
{
|
||||
get => _warn;
|
||||
set => SetProperty( ref _warn, value );
|
||||
}
|
||||
|
||||
public int WarnAmount
|
||||
{
|
||||
get => _warnAmount;
|
||||
set => SetProperty( ref _warnAmount, value );
|
||||
}
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
JObject options = new JObject { { "Warn", Warn }, { "WarnAmount", WarnAmount } };
|
||||
|
||||
JArray items = new JArray();
|
||||
|
||||
foreach ( CountersAgentEntry entry in Items )
|
||||
{
|
||||
JObject entryObj = new JObject
|
||||
{
|
||||
{ "Name", entry.Name }, { "Graphic", entry.Graphic }, { "Color", entry.Color }
|
||||
};
|
||||
|
||||
items.Add( entryObj );
|
||||
}
|
||||
|
||||
options.Add( "Items", items );
|
||||
|
||||
json?.Add( "Counters", options );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Items.Clear();
|
||||
|
||||
if ( json?["Counters"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Warn = json["Counters"]["Warn"]?.ToObject<bool>() ?? false;
|
||||
WarnAmount = json["Counters"]["WarnAmount"]?.ToObject<int>() ?? 0;
|
||||
|
||||
foreach ( JToken token in json["Counters"]["Items"] )
|
||||
{
|
||||
if ( token != null )
|
||||
{
|
||||
Items.Add( new CountersAgentEntry
|
||||
{
|
||||
Name = token["Name"].ToObject<string>() ?? "Unknown",
|
||||
Graphic = token["Graphic"].ToObject<int>(),
|
||||
Color = token["Color"].ToObject<int>()
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveEntry( object obj )
|
||||
{
|
||||
if ( !( obj is CountersAgentEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
}
|
||||
|
||||
private void Recount()
|
||||
{
|
||||
foreach ( CountersAgentEntry item in Items )
|
||||
{
|
||||
int count = item.Count;
|
||||
|
||||
item.Recount();
|
||||
|
||||
if ( Warn && item.Count <= WarnAmount && count > WarnAmount )
|
||||
{
|
||||
Commands.SystemMessage(
|
||||
string.Format( Strings.Counter___0___amount_is_now__1____, item.Name, item.Count ), 61 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InsertEntry( object arg )
|
||||
{
|
||||
int serial = await Commands.GetTargeSerialAsync( Strings.Target_object___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
Commands.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null )
|
||||
{
|
||||
Commands.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
string name = TileData.GetStaticTile( item.ID ).Name;
|
||||
|
||||
if ( string.IsNullOrEmpty( name ) )
|
||||
{
|
||||
name = item.Name;
|
||||
}
|
||||
|
||||
CountersAgentEntry entry = new CountersAgentEntry { Name = name, Graphic = item.ID, Color = item.Hue };
|
||||
|
||||
entry.Recount();
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
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<DressAgentEntry>, ISettingProvider
|
||||
{
|
||||
private readonly IObservable<bool> _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<bool> _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<DressAgentEntry>( ClearDressItems, _entrySelected ) );
|
||||
|
||||
public ICommand DressAllItemsCommand =>
|
||||
_dressAllItemsCommand ?? ( _dressAllItemsCommand =
|
||||
ReactiveCommand.CreateFromTask<DressAgentEntry>( DressAllItems,
|
||||
_entrySelected.Merge( this.WhenAnyValue( e => e.IsDressingOrUndressing, e => !e ) ) ) );
|
||||
|
||||
public ICommand ImportItemsCommand =>
|
||||
_importItemsCommand ?? ( _importItemsCommand =
|
||||
ReactiveCommand.Create<DressAgentEntry>( 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<DressAgentEntry>( RemoveDressEntry, _entrySelected ) );
|
||||
|
||||
public ICommand RemoveDressItemCommand =>
|
||||
_removeDressItemCommand ?? ( _removeDressItemCommand =
|
||||
ReactiveCommand.Create<DressAgentItem>( 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<DressAgentEntry>( SetUndressContainer, _entrySelected ) );
|
||||
|
||||
public ICommand UndressAllItemsCommand =>
|
||||
_undressAllItemsCommand ?? ( _undressAllItemsCommand = ReactiveCommand.CreateFromTask( UndressAllItems,
|
||||
this.WhenAnyValue( e => e.IsDressingOrUndressing, e => !e ) ) );
|
||||
|
||||
public ICommand UndressItemsCommand =>
|
||||
_undressItemsCommand ?? ( _undressItemsCommand =
|
||||
ReactiveCommand.CreateFromTask<DressAgentEntry>( 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<DressAgentItem> items = new List<DressAgentItem>();
|
||||
|
||||
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<DressAgentItem>( 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<DressAgentItem>();
|
||||
}
|
||||
|
||||
private void RemoveDressItem( object obj )
|
||||
{
|
||||
if ( !( obj is DressAgentItem removeItem ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !SelectedItem.Items.Contains( removeItem ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<DressAgentItem> 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<DressAgentItem>() };
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Friends;
|
||||
using ClassicAssist.Data.Macros.Commands;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ClassicAssist.Shared.UI.ViewModels.Agents
|
||||
{
|
||||
public class FriendsTabViewModel : BaseViewModel, ISettingProvider
|
||||
{
|
||||
private ICommand _addFriendCommand;
|
||||
private ICommand _changeRehueOption;
|
||||
private Options _options;
|
||||
private ICommand _removeFriendCommand;
|
||||
private FriendEntry _selectedItem;
|
||||
private ICommand _selectHueCommand;
|
||||
|
||||
public ICommand AddFriendCommand =>
|
||||
_addFriendCommand ?? ( _addFriendCommand = new RelayCommandAsync( AddFriend, o => true ) );
|
||||
|
||||
public ICommand ChangeRehueOption =>
|
||||
_changeRehueOption ?? ( _changeRehueOption = new RelayCommand( ChangeRehue, o => true ) );
|
||||
|
||||
public Options Options
|
||||
{
|
||||
get => _options;
|
||||
set => SetProperty( ref _options, value );
|
||||
}
|
||||
|
||||
public ICommand RemoveFriendCommand =>
|
||||
_removeFriendCommand ?? ( _removeFriendCommand = ReactiveCommand.CreateFromTask<FriendEntry>( RemoveFriend,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
//new RelayCommandAsync( RemoveFriend, o => SelectedItem != null ) );
|
||||
|
||||
public FriendEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public ICommand SelectHueCommand =>
|
||||
_selectHueCommand ?? ( _selectHueCommand = ReactiveCommand.CreateFromTask( SelectHue,
|
||||
this.WhenAnyValue( e => e.Options.RehueFriends, selector: e => e ) ) );
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
JObject config = new JObject
|
||||
{
|
||||
["IncludePartyMembersInFriends"] = Options.IncludePartyMembersInFriends,
|
||||
["PreventAttackingFriendsInWarMode"] = Options.PreventAttackingFriendsInWarMode,
|
||||
["PreventTargetingFriendsWithHarmful"] = Options.PreventTargetingFriendsWithHarmful
|
||||
};
|
||||
|
||||
JArray friends = new JArray();
|
||||
|
||||
foreach ( FriendEntry friend in Options.Friends )
|
||||
{
|
||||
friends.Add( new JObject { { "Name", friend.Name }, { "Serial", friend.Serial } } );
|
||||
}
|
||||
|
||||
config.Add( "Items", friends );
|
||||
|
||||
json?.Add( "Friends", config );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Options = options;
|
||||
Options.Friends.Clear();
|
||||
|
||||
if ( json?["Friends"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JToken config = json["Friends"];
|
||||
|
||||
Options.IncludePartyMembersInFriends = config["IncludePartyMembersInFriends"]?.ToObject<bool>() ?? true;
|
||||
Options.PreventAttackingFriendsInWarMode =
|
||||
config["PreventAttackingFriendsInWarMode"]?.ToObject<bool>() ?? true;
|
||||
Options.PreventTargetingFriendsWithHarmful =
|
||||
config["PreventTargetingFriendsWithHarmful"]?.ToObject<bool>() ?? false;
|
||||
|
||||
if ( config["Items"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( JToken token in config["Items"] )
|
||||
{
|
||||
Options.Friends.Add( new FriendEntry
|
||||
{
|
||||
Name = token["Name"].ToObject<string>(), Serial = token["Serial"].ToObject<int>()
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private static void ChangeRehue( object obj )
|
||||
{
|
||||
MainCommands.Resync();
|
||||
}
|
||||
|
||||
private static async Task SelectHue( CancellationToken token )
|
||||
{
|
||||
int hue = await Engine.UIInvoker.GetHueAsync();
|
||||
|
||||
Options.CurrentOptions.RehueFriendsHue = hue;
|
||||
MainCommands.Resync();
|
||||
}
|
||||
|
||||
private static async Task AddFriend( object arg )
|
||||
{
|
||||
await Task.Run( () => MobileCommands.AddFriend() );
|
||||
}
|
||||
|
||||
private static Task RemoveFriend( object arg )
|
||||
{
|
||||
if ( !( arg is FriendEntry fe ) )
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
MobileCommands.RemoveFriend( fe.Serial );
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Hotkeys;
|
||||
using ClassicAssist.Data.Organizer;
|
||||
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 OrganizerTabViewModel : HotkeyEntryViewModel<OrganizerEntry>, ISettingProvider
|
||||
{
|
||||
private readonly OrganizerManager _manager;
|
||||
private ReactiveCommand<OrganizerEntry, Unit> _insertItemCommand;
|
||||
private bool _isOrganizing;
|
||||
private ICommand _newOrganizerEntryCommand;
|
||||
private ReactiveCommand<OrganizerEntry, Unit> _organizeCommand;
|
||||
private ReactiveCommand<OrganizerItem, Unit> _removeItemCommand;
|
||||
private ReactiveCommand<OrganizerEntry, Unit> _removeOrganizerAgentEntryCommand;
|
||||
private OrganizerEntry _selectedItem;
|
||||
private OrganizerItem _selectedOrganizerItem;
|
||||
private ReactiveCommand<OrganizerEntry, Unit> _setContainersCommand;
|
||||
|
||||
public OrganizerTabViewModel() : base( Strings.Organizer )
|
||||
{
|
||||
_manager = OrganizerManager.GetInstance();
|
||||
|
||||
_manager.Items = Items;
|
||||
}
|
||||
|
||||
public ReactiveCommand<OrganizerEntry, Unit> InsertItemCommand =>
|
||||
_insertItemCommand ?? ( _insertItemCommand = ReactiveCommand.CreateFromTask<OrganizerEntry>( InsertItem,
|
||||
this.WhenAnyValue( e => e.SelectedItem, e => e.IsOrganizing, ( e, f ) => e != null && !f ) ) );
|
||||
|
||||
public bool IsOrganizing
|
||||
{
|
||||
get => _isOrganizing;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _isOrganizing, value );
|
||||
NotifyPropertyChanged( nameof( PlayStopButtonText ) );
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand NewOrganizerEntryCommand =>
|
||||
_newOrganizerEntryCommand ??
|
||||
( _newOrganizerEntryCommand = new RelayCommand( NewOrganizerEntry, o => !IsOrganizing ) );
|
||||
|
||||
public ReactiveCommand<OrganizerEntry, Unit> OrganizeCommand =>
|
||||
_organizeCommand ?? ( _organizeCommand = ReactiveCommand.CreateFromTask<OrganizerEntry>( Organize,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
|
||||
public string PlayStopButtonText => IsOrganizing ? Strings.Stop : Strings.Play;
|
||||
|
||||
public ReactiveCommand<OrganizerItem, Unit> RemoveItemCommand =>
|
||||
_removeItemCommand ?? ( _removeItemCommand = ReactiveCommand.Create<OrganizerItem>( RemoveItem,
|
||||
this.WhenAnyValue( e => e.IsOrganizing, e => e.SelectedOrganizerItem, ( e, f ) => !e && f != null ) ) );
|
||||
|
||||
public ReactiveCommand<OrganizerEntry, Unit> RemoveOrganizerAgentEntryCommand =>
|
||||
_removeOrganizerAgentEntryCommand ?? ( _removeOrganizerAgentEntryCommand =
|
||||
ReactiveCommand.Create<OrganizerEntry>( RemoveOrganizerAgentEntry,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
|
||||
public OrganizerEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public OrganizerItem SelectedOrganizerItem
|
||||
{
|
||||
get => _selectedOrganizerItem;
|
||||
set => SetProperty( ref _selectedOrganizerItem, value );
|
||||
}
|
||||
|
||||
public ReactiveCommand<OrganizerEntry, Unit> SetContainersCommand =>
|
||||
_setContainersCommand ?? ( _setContainersCommand =
|
||||
ReactiveCommand.CreateFromTask<OrganizerEntry>( _manager.SetContainers,
|
||||
this.WhenAnyValue( e => e.SelectedItem, f => f.IsOrganizing, ( e, f ) => e != null && !f ) ) );
|
||||
//new RelayCommandAsync( _manager.SetContainers, o => SelectedItem != null && !IsOrganizing ) );
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
JArray organizer = new JArray();
|
||||
|
||||
foreach ( OrganizerEntry organizerEntry in Items )
|
||||
{
|
||||
JObject entryObj = new JObject();
|
||||
|
||||
SetJsonValue( entryObj, "Name", organizerEntry.Name );
|
||||
SetJsonValue( entryObj, "Stack", organizerEntry.Stack );
|
||||
SetJsonValue( entryObj, "SourceContainer", organizerEntry.SourceContainer );
|
||||
SetJsonValue( entryObj, "DestinationContainer", organizerEntry.DestinationContainer );
|
||||
SetJsonValue( entryObj, "Keys", organizerEntry.Hotkey.ToJObject() );
|
||||
SetJsonValue( entryObj, "Complete", organizerEntry.Complete );
|
||||
|
||||
JArray itemsArray = new JArray();
|
||||
|
||||
foreach ( OrganizerItem organizerItem in organizerEntry.Items )
|
||||
{
|
||||
JObject itemsObj = new JObject();
|
||||
|
||||
SetJsonValue( itemsObj, "Item", organizerItem.Item );
|
||||
SetJsonValue( itemsObj, "ID", organizerItem.ID );
|
||||
SetJsonValue( itemsObj, "Hue", organizerItem.Hue );
|
||||
SetJsonValue( itemsObj, "Amount", organizerItem.Amount );
|
||||
|
||||
itemsArray.Add( itemsObj );
|
||||
}
|
||||
|
||||
entryObj.Add( "Items", itemsArray );
|
||||
|
||||
organizer.Add( entryObj );
|
||||
}
|
||||
|
||||
json?.Add( "Organizer", organizer );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Items.Clear();
|
||||
|
||||
if ( json?["Organizer"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( JToken token in json["Organizer"] )
|
||||
{
|
||||
OrganizerEntry entry = new OrganizerEntry
|
||||
{
|
||||
Name = GetJsonValue( token, "Name", "Organizer" ),
|
||||
Stack = GetJsonValue( token, "Stack", true ),
|
||||
SourceContainer = GetJsonValue( token, "SourceContainer", 0 ),
|
||||
DestinationContainer = GetJsonValue( token, "DestinationContainer", 0 ),
|
||||
Hotkey = new ShortcutKeys( token["Keys"] ),
|
||||
Complete = GetJsonValue( token, "Complete", false )
|
||||
};
|
||||
|
||||
entry.Action = hks => Task.Run( async () => await _manager.Organize( entry ) );
|
||||
entry.IsRunning = () => IsOrganizing;
|
||||
|
||||
foreach ( JToken itemToken in token["Items"] )
|
||||
{
|
||||
OrganizerItem item = new OrganizerItem
|
||||
{
|
||||
Item = GetJsonValue( itemToken, "Item", string.Empty ),
|
||||
ID = GetJsonValue( itemToken, "ID", 0 ),
|
||||
Hue = GetJsonValue( itemToken, "Hue", -1 ),
|
||||
Amount = GetJsonValue( itemToken, "Amount", -1 )
|
||||
};
|
||||
|
||||
entry.Items.Add( item );
|
||||
}
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Organize( object arg )
|
||||
{
|
||||
if ( !( arg is OrganizerEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsOrganizing = true;
|
||||
|
||||
await _manager.Organize( entry );
|
||||
|
||||
IsOrganizing = false;
|
||||
}
|
||||
|
||||
private void NewOrganizerEntry( object obj )
|
||||
{
|
||||
int count = Items.Count + 1;
|
||||
|
||||
OrganizerEntry entry = new OrganizerEntry
|
||||
{
|
||||
Name = $"Organizer-{count}",
|
||||
Action = hks => Task.Run( async () => await _manager.Organize( SelectedItem ) ),
|
||||
IsRunning = () => IsOrganizing
|
||||
};
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
|
||||
private void RemoveOrganizerAgentEntry( object obj )
|
||||
{
|
||||
if ( !( obj is OrganizerEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
}
|
||||
|
||||
private void RemoveItem( object obj )
|
||||
{
|
||||
if ( !( obj is OrganizerItem item ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectedItem.Items.Remove( item );
|
||||
}
|
||||
|
||||
private static async Task InsertItem( object arg )
|
||||
{
|
||||
if ( !( arg is OrganizerEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int serial = await Commands.GetTargeSerialAsync( Strings.Target_new_item___ );
|
||||
|
||||
if ( serial <= 0 )
|
||||
{
|
||||
Commands.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null )
|
||||
{
|
||||
Commands.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
OrganizerItem organizerItem = new OrganizerItem
|
||||
{
|
||||
Item = TileData.GetStaticTile( item.ID ).Name, ID = item.ID, Hue = item.Hue, Amount = -1
|
||||
};
|
||||
|
||||
entry.Items.Add( organizerItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Scavenger;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
using ClassicAssist.UO.Data;
|
||||
using ClassicAssist.UO.Network;
|
||||
using ClassicAssist.UO.Objects;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ReactiveUI;
|
||||
using UOC = ClassicAssist.Shared.UO.Commands;
|
||||
|
||||
namespace ClassicAssist.Shared.UI.ViewModels.Agents
|
||||
{
|
||||
public class ScavengerTabViewModel : BaseViewModel, ISettingProvider
|
||||
{
|
||||
private const int SCAVENGER_DISTANCE = 2;
|
||||
private readonly List<int> _ignoreList;
|
||||
private readonly object _scavengeLock = new object();
|
||||
private ICommand _clearAllCommand;
|
||||
private int _containerSerial;
|
||||
private bool _enabled;
|
||||
private ICommand _insertCommand;
|
||||
private ObservableCollection<ScavengerEntry> _items = new ObservableCollection<ScavengerEntry>();
|
||||
private ICommand _removeCommand;
|
||||
private ScavengerEntry _selectedItem;
|
||||
private ICommand _setContainerCommand;
|
||||
|
||||
public ScavengerTabViewModel()
|
||||
{
|
||||
ScavengerManager manager = ScavengerManager.GetInstance();
|
||||
manager.Items = Items;
|
||||
manager.CheckArea = () => Task.Run( CheckArea );
|
||||
_ignoreList = new List<int>();
|
||||
}
|
||||
|
||||
public ICommand ClearAllCommand =>
|
||||
_clearAllCommand ?? ( _clearAllCommand = ReactiveCommand.CreateFromTask( ClearAll ) );
|
||||
|
||||
public int ContainerSerial
|
||||
{
|
||||
get => _containerSerial;
|
||||
set => SetProperty( ref _containerSerial, value );
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set => SetProperty( ref _enabled, value );
|
||||
}
|
||||
|
||||
public ICommand InsertCommand =>
|
||||
_insertCommand ?? ( _insertCommand = new RelayCommandAsync( Insert, o => true ) );
|
||||
|
||||
public ObservableCollection<ScavengerEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand RemoveCommand =>
|
||||
_removeCommand ?? ( _removeCommand = ReactiveCommand.CreateFromTask<ScavengerEntry>( Remove,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
|
||||
public ScavengerEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public ICommand SetContainerCommand =>
|
||||
_setContainerCommand ?? ( _setContainerCommand = new RelayCommandAsync( SetContainer, o => true ) );
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
Engine.Items.CollectionChanged -= ItemsOnCollectionChanged;
|
||||
|
||||
if ( json == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JObject scavengerObj = new JObject { { "Enabled", Enabled }, { "Container", ContainerSerial } };
|
||||
|
||||
JArray itemsArray = new JArray();
|
||||
|
||||
foreach ( ScavengerEntry entry in Items )
|
||||
{
|
||||
itemsArray.Add( new JObject
|
||||
{
|
||||
{ "Graphic", entry.Graphic },
|
||||
{ "Name", entry.Name },
|
||||
{ "Hue", entry.Hue },
|
||||
{ "Enabled", entry.Enabled }
|
||||
} );
|
||||
}
|
||||
|
||||
scavengerObj.Add( "Items", itemsArray );
|
||||
|
||||
json.Add( "Scavenger", scavengerObj );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Engine.Items.CollectionChanged += ItemsOnCollectionChanged;
|
||||
Items.Clear();
|
||||
|
||||
if ( json?["Scavenger"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JToken config = json["Scavenger"];
|
||||
|
||||
Enabled = config["Enabled"]?.ToObject<bool>() ?? true;
|
||||
ContainerSerial = config["Container"]?.ToObject<int>() ?? 0;
|
||||
|
||||
if ( config["Items"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( JToken token in config["Items"] )
|
||||
{
|
||||
ScavengerEntry entry = new ScavengerEntry
|
||||
{
|
||||
Graphic = token["Graphic"]?.ToObject<int>() ?? 0,
|
||||
Name = token["Name"]?.ToObject<string>() ?? "Unknown",
|
||||
Hue = token["Hue"]?.ToObject<int>() ?? 0,
|
||||
Enabled = token["Enabled"]?.ToObject<bool>() ?? true
|
||||
};
|
||||
|
||||
bool alreadyExists = Items.Any( s => s.Graphic == entry.Graphic && s.Hue == entry.Hue );
|
||||
|
||||
if ( !alreadyExists )
|
||||
{
|
||||
Items.Add( entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemsOnCollectionChanged( int totalcount, bool added, Item[] items )
|
||||
{
|
||||
if ( !added || !Enabled )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasNearby = items.Any( i => i.Distance <= SCAVENGER_DISTANCE );
|
||||
|
||||
if ( hasNearby )
|
||||
{
|
||||
CheckArea();
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckArea()
|
||||
{
|
||||
if ( !Enabled || Engine.Player == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<Item> scavengerItems = new List<Item>();
|
||||
|
||||
if ( Engine.Player.WeightMax - Engine.Player.Weight <= 25 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock ( _scavengeLock )
|
||||
{
|
||||
foreach ( ScavengerEntry entry in Items )
|
||||
{
|
||||
if ( !entry.Enabled )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Item[] matches = Engine.Items.SelectEntities( i =>
|
||||
i.Distance <= SCAVENGER_DISTANCE && i.Owner == 0 && i.ID == entry.Graphic &&
|
||||
( entry.Hue == -1 || i.Hue == entry.Hue ) && !_ignoreList.Contains( i.Serial ) );
|
||||
|
||||
if ( matches == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scavengerItems.AddRange( matches );
|
||||
}
|
||||
|
||||
if ( scavengerItems.Count == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Item container = Engine.Items.GetItem( _containerSerial ) ?? Engine.Player.Backpack;
|
||||
|
||||
if ( container == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( Item scavengerItem in scavengerItems.Where( scavengerItem =>
|
||||
scavengerItem.Distance <= SCAVENGER_DISTANCE ).Distinct() )
|
||||
{
|
||||
_ignoreList.Add( scavengerItem.Serial );
|
||||
UOC.SystemMessage( string.Format( Strings.Scavenging___0__, scavengerItem.Name ?? "Unknown" ), 61 );
|
||||
ActionPacketQueue.EnqueueDragDrop( scavengerItem.Serial, scavengerItem.Count, container.Serial,
|
||||
QueuePriority.Low, true ).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Insert( object arg )
|
||||
{
|
||||
int serial = await UOC.GetTargeSerialAsync( Strings.Target_object___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
string tiledataName = TileData.GetStaticTile( item.ID ).Name ?? "Unknown";
|
||||
|
||||
ScavengerEntry entry =
|
||||
new ScavengerEntry { Enabled = true, Graphic = item.ID, Hue = item.Hue, Name = tiledataName };
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
|
||||
private async Task Remove( object arg )
|
||||
{
|
||||
if ( !( arg is ScavengerEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task ClearAll( CancellationToken cancellationToken )
|
||||
{
|
||||
Items.Clear();
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SetContainer( object arg )
|
||||
{
|
||||
int serial = await UOC.GetTargeSerialAsync( Strings.Select_destination_container___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Invalid_container___ );
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerSerial = serial;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Macros;
|
||||
using ClassicAssist.Data.Macros.Commands;
|
||||
using ClassicAssist.Data.Vendors;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
using ClassicAssist.UO.Data;
|
||||
using ClassicAssist.UO.Network;
|
||||
using ClassicAssist.UO.Objects;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ReactiveUI;
|
||||
using UOC = ClassicAssist.Shared.UO.Commands;
|
||||
|
||||
namespace ClassicAssist.Shared.UI.ViewModels.Agents
|
||||
{
|
||||
public class VendorBuyTabViewModel : BaseViewModel, ISettingProvider
|
||||
{
|
||||
private bool _enabled;
|
||||
private bool _includeBackpackAmount;
|
||||
private bool _includePurchasedAmount;
|
||||
private ICommand _insertCommand;
|
||||
private ObservableCollection<VendorBuyAgentEntry> _items = new ObservableCollection<VendorBuyAgentEntry>();
|
||||
private ICommand _removeCommand;
|
||||
private VendorBuyAgentEntry _selectedItem;
|
||||
|
||||
public VendorBuyTabViewModel()
|
||||
{
|
||||
IncomingPacketHandlers.VendorBuyDisplayEvent += OnVendorBuyDisplayEvent;
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set => SetProperty( ref _enabled, value );
|
||||
}
|
||||
|
||||
public bool IncludeBackpackAmount
|
||||
{
|
||||
get => _includeBackpackAmount;
|
||||
set => SetProperty( ref _includeBackpackAmount, value );
|
||||
}
|
||||
|
||||
public bool IncludePurchasedAmount
|
||||
{
|
||||
get => _includePurchasedAmount;
|
||||
set => SetProperty( ref _includePurchasedAmount, value );
|
||||
}
|
||||
|
||||
public ICommand InsertCommand =>
|
||||
_insertCommand ?? ( _insertCommand = ReactiveCommand.CreateFromTask( Insert ) );
|
||||
|
||||
public ObservableCollection<VendorBuyAgentEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand RemoveCommand =>
|
||||
_removeCommand ?? ( _removeCommand = ReactiveCommand.Create<VendorBuyAgentEntry>( Remove,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
|
||||
public VendorBuyAgentEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
if ( json == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JObject config = new JObject
|
||||
{
|
||||
{ "Enabled", Enabled },
|
||||
{ "IncludeBackpackAmount", IncludeBackpackAmount },
|
||||
{ "IncludePurchasedAmount", IncludePurchasedAmount }
|
||||
};
|
||||
|
||||
JArray itemObj = new JArray();
|
||||
|
||||
foreach ( VendorBuyAgentEntry entry in Items )
|
||||
{
|
||||
JObject entryObj = new JObject
|
||||
{
|
||||
{ "Enabled", entry.Enabled },
|
||||
{ "Name", entry.Name },
|
||||
{ "Graphic", entry.Graphic },
|
||||
{ "Hue", entry.Hue },
|
||||
{ "Amount", entry.Amount },
|
||||
{ "MaxPrice", entry.MaxPrice }
|
||||
};
|
||||
|
||||
itemObj.Add( entryObj );
|
||||
}
|
||||
|
||||
config.Add( "Items", itemObj );
|
||||
|
||||
json.Add( "VendorBuy", config );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Items.Clear();
|
||||
|
||||
if ( json?["VendorBuy"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JToken config = json["VendorBuy"];
|
||||
|
||||
Enabled = config["Enabled"]?.ToObject<bool>() ?? false;
|
||||
IncludeBackpackAmount = config["IncludeBackpackAmount"]?.ToObject<bool>() ?? false;
|
||||
IncludePurchasedAmount = config["IncludePurchasedAmount"]?.ToObject<bool>() ?? false;
|
||||
|
||||
foreach ( JToken token in config["Items"] )
|
||||
{
|
||||
VendorBuyAgentEntry vbae = new VendorBuyAgentEntry
|
||||
{
|
||||
Enabled = token["Enabled"]?.ToObject<bool>() ?? false,
|
||||
Name = token["Name"]?.ToObject<string>() ?? "Unknown",
|
||||
Graphic = token["Graphic"]?.ToObject<int>() ?? 0,
|
||||
Hue = token["Hue"]?.ToObject<int>() ?? 0,
|
||||
Amount = token["Amount"]?.ToObject<int>() ?? 0,
|
||||
MaxPrice = token["MaxPrice"]?.ToObject<int>() ?? 0
|
||||
};
|
||||
|
||||
Items.Add( vbae );
|
||||
}
|
||||
}
|
||||
|
||||
private void OnVendorBuyDisplayEvent( int serial, ShopListEntry[] entries )
|
||||
{
|
||||
if ( !Enabled )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IEnumerable<VendorBuyAgentEntry> items = Items.Where( i => i.Enabled );
|
||||
|
||||
List<ShopListEntry> buyList = new List<ShopListEntry>();
|
||||
|
||||
foreach ( VendorBuyAgentEntry entry in items )
|
||||
{
|
||||
IEnumerable<ShopListEntry> matches = entries.Where( i =>
|
||||
i.Item.ID == entry.Graphic && ( entry.Hue == -1 || i.Item.Hue == entry.Hue ) &&
|
||||
( entry.MaxPrice == -1 || i.Price <= entry.MaxPrice ) );
|
||||
|
||||
foreach ( ShopListEntry match in matches )
|
||||
{
|
||||
if ( entry.Amount != -1 )
|
||||
{
|
||||
if ( match.Amount > entry.Amount )
|
||||
{
|
||||
match.Amount = entry.Amount;
|
||||
}
|
||||
|
||||
if ( IncludeBackpackAmount )
|
||||
{
|
||||
int currentAmount = ObjectCommands.CountType( entry.Graphic, "backpack", entry.Hue );
|
||||
|
||||
if ( currentAmount + match.Amount > entry.Amount )
|
||||
{
|
||||
match.Amount = entry.Amount - currentAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( match.Amount > 0 )
|
||||
{
|
||||
buyList.Add( match );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( buyList.Count > 0 )
|
||||
{
|
||||
UOC.VendorBuy( serial, buyList.ToArray() );
|
||||
}
|
||||
|
||||
if ( !MacroManager.QuietMode && buyList.Count == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Buy_Agent__No_matches_found_ );
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Insert( CancellationToken cancellationToken )
|
||||
{
|
||||
int serial = await UOC.GetTargeSerialAsync( Strings.Target_object___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
string name = TileData.GetStaticTile( item.ID ).Name ?? item.Name;
|
||||
|
||||
Items.Add( new VendorBuyAgentEntry
|
||||
{
|
||||
Enabled = true,
|
||||
Name = name,
|
||||
Graphic = item.ID,
|
||||
Amount = -1,
|
||||
Hue = item.Hue,
|
||||
MaxPrice = -1
|
||||
} );
|
||||
}
|
||||
|
||||
private void Remove( object obj )
|
||||
{
|
||||
if ( !( obj is VendorBuyAgentEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Data.Vendors;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
using ClassicAssist.UO.Data;
|
||||
using ClassicAssist.UO.Network;
|
||||
using ClassicAssist.UO.Objects;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ReactiveUI;
|
||||
using UOC = ClassicAssist.Shared.UO.Commands;
|
||||
|
||||
namespace ClassicAssist.Shared.UI.ViewModels.Agents
|
||||
{
|
||||
public class VendorSellTabViewModel : BaseViewModel, ISettingProvider
|
||||
{
|
||||
private ICommand _insertCommand;
|
||||
private ObservableCollection<VendorSellAgentEntry> _items = new ObservableCollection<VendorSellAgentEntry>();
|
||||
private ICommand _removeCommand;
|
||||
private VendorSellAgentEntry _selectedItem;
|
||||
|
||||
public VendorSellTabViewModel()
|
||||
{
|
||||
IncomingPacketHandlers.VendorSellDisplayEvent += OnVendorSellDisplayEvent;
|
||||
}
|
||||
|
||||
public ICommand InsertCommand =>
|
||||
_insertCommand ?? ( _insertCommand = ReactiveCommand.CreateFromTask( Insert ) );
|
||||
|
||||
public ObservableCollection<VendorSellAgentEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand RemoveCommand =>
|
||||
_removeCommand ?? ( _removeCommand = ReactiveCommand.Create<VendorSellAgentEntry>( Remove,
|
||||
this.WhenAnyValue( e => e.SelectedItem, selector: e => e != null ) ) );
|
||||
|
||||
public VendorSellAgentEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
public void Serialize( JObject json )
|
||||
{
|
||||
if ( json == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JArray itemsObj = new JArray();
|
||||
|
||||
foreach ( VendorSellAgentEntry item in Items )
|
||||
{
|
||||
JObject itemObj = new JObject
|
||||
{
|
||||
{ "Enabled", item.Enabled },
|
||||
{ "Graphic", item.Graphic },
|
||||
{ "Hue", item.Hue },
|
||||
{ "Amount", item.Amount },
|
||||
{ "MinPrice", item.MinPrice },
|
||||
{ "Name", item.Name }
|
||||
};
|
||||
|
||||
itemsObj.Add( itemObj );
|
||||
}
|
||||
|
||||
JObject config = new JObject { { "Items", itemsObj } };
|
||||
|
||||
json.Add( "VendorSell", config );
|
||||
}
|
||||
|
||||
public void Deserialize( JObject json, Options options )
|
||||
{
|
||||
Items.Clear();
|
||||
|
||||
if ( json?["VendorSell"] == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JToken config = json["VendorSell"];
|
||||
|
||||
foreach ( JToken items in config?["Items"] )
|
||||
{
|
||||
VendorSellAgentEntry vsae = new VendorSellAgentEntry
|
||||
{
|
||||
Enabled = items["Enabled"]?.ToObject<bool>() ?? true,
|
||||
Graphic = items["Graphic"]?.ToObject<int>() ?? 0,
|
||||
Hue = items["Hue"]?.ToObject<int>() ?? 0,
|
||||
Amount = items["Amount"]?.ToObject<int>() ?? -1,
|
||||
MinPrice = items["MinPrice"]?.ToObject<int>() ?? 0,
|
||||
Name = items["Name"]?.ToObject<string>() ?? string.Empty
|
||||
};
|
||||
|
||||
Items.Add( vsae );
|
||||
}
|
||||
}
|
||||
|
||||
private void Remove( object arg )
|
||||
{
|
||||
if ( !( arg is VendorSellAgentEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
}
|
||||
|
||||
private void OnVendorSellDisplayEvent( int serial, SellListEntry[] entries )
|
||||
{
|
||||
List<SellListEntry> sellList = new List<SellListEntry>();
|
||||
|
||||
foreach ( SellListEntry entry in entries )
|
||||
{
|
||||
VendorSellAgentEntry match = Items.FirstOrDefault( i =>
|
||||
i.Graphic == entry.ID && ( i.Hue == -1 || i.Hue == entry.Hue ) && entry.Price >= i.MinPrice &&
|
||||
i.Enabled );
|
||||
|
||||
if ( match != null && match.Amount != -1 )
|
||||
{
|
||||
entry.Amount = Math.Min( match.Amount, entry.Amount );
|
||||
}
|
||||
|
||||
if ( match != null )
|
||||
{
|
||||
sellList.Add( entry );
|
||||
}
|
||||
}
|
||||
|
||||
if ( sellList.Count > 0 )
|
||||
{
|
||||
Sell( serial, sellList.ToArray() );
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sell( int vendorSerial, SellListEntry[] entries )
|
||||
{
|
||||
if ( entries == null || entries.Length == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int len = 9 + entries.Length * 6;
|
||||
|
||||
PacketWriter pw = new PacketWriter( len );
|
||||
pw.Write( (byte) 0x9F );
|
||||
pw.Write( (short) len );
|
||||
pw.Write( vendorSerial );
|
||||
pw.Write( (short) entries.Length );
|
||||
|
||||
foreach ( SellListEntry entry in entries )
|
||||
{
|
||||
pw.Write( entry.Serial );
|
||||
pw.Write( (short) entry.Amount );
|
||||
}
|
||||
|
||||
Engine.SendPacketToServer( pw );
|
||||
}
|
||||
|
||||
private async Task Insert( CancellationToken cancellationToken )
|
||||
{
|
||||
int serial = await UOC.GetTargeSerialAsync( Strings.Target_object___ );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Invalid_or_unknown_object_id );
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = Engine.Items.GetItem( serial );
|
||||
|
||||
if ( item == null )
|
||||
{
|
||||
UOC.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
string name = TileData.GetStaticTile( item.ID ).Name ?? item.Name;
|
||||
|
||||
Items.Add( new VendorSellAgentEntry
|
||||
{
|
||||
Enabled = true,
|
||||
Name = name,
|
||||
Graphic = item.ID,
|
||||
Hue = item.Hue,
|
||||
Amount = -1,
|
||||
MinPrice = 0
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user