first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
@@ -0,0 +1,336 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using ClassicAssist.Data.Macros;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UO;
namespace ClassicAssist.UI.ViewModels
{
public class TimerData
{
public string Name { get; set; }
public OffsetStopwatch Value { get; set; }
}
public class ActiveObjectsViewModel : BaseViewModel
{
private ICommand _clearAllAliasesCommand;
private ICommand _clearAllListsCommand;
private ICommand _clearIgnoreListCommand;
private ObservableCollection<int> _ignoreEntries = new ObservableCollection<int>();
private ICommand _refreshAliasesCommand;
private ICommand _refreshIgnoreListCommand;
private ICommand _refreshListsCommand;
private ICommand _refreshTimersCommand;
private ICommand _removeAliasCommand;
private ICommand _removeIgnoreEntryCommand;
private ICommand _removeInstanceAliasCommand;
private ICommand _removeListCommand;
private AliasEntry _selectedAlias;
private int _selectedIgnoreEntry;
private InstanceAliasEntry _selectedInstanceAlias;
private ListEntry _selectedList;
private TimerData _selectedTimer;
private ICommand _setAliasCommand;
private ObservableCollection<TimerData> _timers = new ObservableCollection<TimerData>();
public ActiveObjectsViewModel()
{
RefreshAliases();
RefreshInstanceAliases();
RefreshLists();
RefreshTimers();
RefreshIgnoreList();
}
public ObservableCollection<AliasEntry> Aliases { get; set; } = new ObservableCollection<AliasEntry>();
public ICommand ClearAllAliasesCommand =>
_clearAllAliasesCommand ?? ( _clearAllAliasesCommand = new RelayCommand( ClearAllAliases, o => true ) );
public ICommand ClearAllListsCommand =>
_clearAllListsCommand ?? ( _clearAllListsCommand = new RelayCommand( ClearAllLists, o => true ) );
public ICommand ClearIgnoreListCommand =>
_clearIgnoreListCommand ?? ( _clearIgnoreListCommand = new RelayCommand( ClearIgnoreList, o => true ) );
public ObservableCollection<int> IgnoreEntries
{
get => _ignoreEntries;
set => SetProperty( ref _ignoreEntries, value );
}
public ObservableCollection<InstanceAliasEntry> InstanceAliases { get; set; } =
new ObservableCollection<InstanceAliasEntry>();
public ObservableCollection<ListEntry> Lists { get; set; } = new ObservableCollection<ListEntry>();
public ICommand RefreshAliasesCommand =>
_refreshAliasesCommand ?? ( _refreshAliasesCommand = new RelayCommand( o => RefreshAliases(), o => true ) );
public ICommand RefreshIgnoreListCommand =>
_refreshIgnoreListCommand ??
( _refreshIgnoreListCommand = new RelayCommand( o => RefreshIgnoreList(), o => true ) );
public ICommand RefreshListsCommand =>
_refreshListsCommand ?? ( _refreshListsCommand = new RelayCommand( o => RefreshLists(), o => true ) );
public ICommand RefreshTimersCommand =>
_refreshTimersCommand ?? ( _refreshTimersCommand = new RelayCommand( o => RefreshTimers(), o => true ) );
public ICommand RemoveAliasCommand =>
_removeAliasCommand ??
( _removeAliasCommand = new RelayCommand( RemoveAlias, o => SelectedAlias != null ) );
public ICommand RemoveIgnoreEntryCommand =>
_removeIgnoreEntryCommand ??
( _removeIgnoreEntryCommand = new RelayCommand( RemoveIgnoreEntry, o => true ) );
public ICommand RemoveInstanceAliasCommand =>
_removeInstanceAliasCommand ?? ( _removeInstanceAliasCommand =
new RelayCommand( RemoveInstanceAlias, o => SelectedInstanceAlias != null ) );
public ICommand RemoveListCommand =>
_removeListCommand ?? ( _removeListCommand = new RelayCommand( RemoveList, o => SelectedList != null ) );
public AliasEntry SelectedAlias
{
get => _selectedAlias;
set => SetProperty( ref _selectedAlias, value );
}
public int SelectedIgnoreEntry
{
get => _selectedIgnoreEntry;
set => SetProperty( ref _selectedIgnoreEntry, value );
}
public InstanceAliasEntry SelectedInstanceAlias
{
get => _selectedInstanceAlias;
set => SetProperty( ref _selectedInstanceAlias, value );
}
public ListEntry SelectedList
{
get => _selectedList;
set => SetProperty( ref _selectedList, value );
}
public TimerData SelectedTimer
{
get => _selectedTimer;
set => SetProperty( ref _selectedTimer, value );
}
public ICommand SetAliasCommand =>
_setAliasCommand ?? ( _setAliasCommand = new RelayCommandAsync( SetAlias, o => o != null ) );
public ObservableCollection<TimerData> Timers
{
get => _timers;
set => SetProperty( ref _timers, value );
}
private void RefreshInstanceAliases()
{
InstanceAliases.Clear();
MacroManager manager = MacroManager.GetInstance();
foreach ( MacroEntry entry in manager.Items )
{
foreach ( KeyValuePair<string, int> alias in entry.Aliases )
{
InstanceAliases.Add( new InstanceAliasEntry
{
Macro = entry, Name = alias.Key, Serial = alias.Value
} );
}
}
}
private void RemoveInstanceAlias( object obj )
{
if ( !( obj is InstanceAliasEntry entry ) )
{
return;
}
entry.Macro.Aliases.Remove( entry.Name );
RefreshInstanceAliases();
}
private void ClearIgnoreList( object obj )
{
ObjectCommands.ClearIgnoreList();
RefreshIgnoreList();
}
private void RemoveIgnoreEntry( object obj )
{
if ( !( obj is int serial ) )
{
return;
}
ObjectCommands.IgnoreList.Remove( serial );
RefreshIgnoreList();
}
private void RefreshIgnoreList()
{
IgnoreEntries.Clear();
foreach ( int serial in ObjectCommands.IgnoreList )
{
IgnoreEntries.Add( serial );
}
}
private void RefreshTimers()
{
Dictionary<string, OffsetStopwatch> timers = TimerCommands.GetAllTimers();
if ( timers == null )
{
return;
}
Timers.Clear();
foreach ( KeyValuePair<string, OffsetStopwatch> timer in timers )
{
Timers.Add( new TimerData { Name = timer.Key, Value = timer.Value } );
}
}
private void RemoveList( object obj )
{
if ( !( obj is ListEntry entry ) )
{
return;
}
ListCommands.RemoveList( entry.Name );
Lists.Remove( entry );
}
private void ClearAllLists( object obj )
{
string[] lists = ListCommands.GetAllLists().Select( l => l.Key ).ToArray();
for ( int i = 0; i < lists.Count(); i++ )
{
ListCommands.RemoveList( lists[i] );
}
RefreshLists();
}
private void RefreshLists()
{
Lists.Clear();
foreach ( KeyValuePair<string, List<int>> list in ListCommands.GetAllLists() )
{
Lists.Add( new ListEntry { Name = list.Key, Serials = list.Value.ToArray() } );
}
}
private void RemoveAlias( object obj )
{
if ( !( obj is AliasEntry entry ) )
{
return;
}
AliasCommands.UnsetAlias( entry.Name );
Aliases.Remove( entry );
}
public void RefreshAliases()
{
Aliases.Clear();
foreach ( KeyValuePair<string, int> alias in AliasCommands.GetAllAliases() )
{
Aliases.AddSorted( new AliasEntry { Name = alias.Key, Serial = alias.Value } );
}
}
private void ClearAllAliases( object obj )
{
string[] aliases = AliasCommands.GetAllAliases().Select( a => a.Key ).ToArray();
// ReSharper disable once ForCanBeConvertedToForeach
for ( int i = 0; i < aliases.Length; i++ )
{
AliasCommands.UnsetAlias( aliases[i] );
}
RefreshAliases();
}
private static async Task SetAlias( object arg )
{
if ( !( arg is AliasEntry entry ) )
{
return;
}
int serial =
await Shared.UO.Commands.GetTargeSerialAsync( string.Format( Strings.Target_object___0_____, entry.Name ) );
if ( serial == 0 )
{
return;
}
AliasCommands.SetAlias( entry.Name, serial );
}
public class InstanceAliasEntry
{
public MacroEntry Macro { get; set; }
public string Name { get; set; }
public int Serial { get; set; }
}
public class AliasEntry : IComparable<AliasEntry>
{
public string Name { get; set; }
public int Serial { get; set; }
public int CompareTo( AliasEntry other )
{
if ( ReferenceEquals( this, other ) )
{
return 0;
}
if ( ReferenceEquals( null, other ) )
{
return 1;
}
return string.Compare( Name, other.Name, StringComparison.InvariantCultureIgnoreCase );
}
}
public class ListEntry
{
public string Name { get; set; }
public int[] Serials { get; set; }
}
}
}
@@ -0,0 +1,260 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Input;
using System.Windows.Media;
using ClassicAssist.Shared;
using ClassicAssist.Data.Chat;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.Shared.UO;
namespace ClassicAssist.UI.ViewModels
{
public class ChatViewModel : BaseViewModel
{
private readonly SolidColorBrush _defaultBrush =
new SolidColorBrush( Color.FromArgb( 0xff, 0xcc, 0xcc, 0xcc ) );
private readonly SolidColorBrush _enemyBrush = new SolidColorBrush( Colors.Orange );
private readonly SolidColorBrush _friendBrush = new SolidColorBrush( Colors.LimeGreen );
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
private readonly ChatManager _manager;
private ICommand _changeChannelCommand;
private ObservableCollection<string> _channels = new ObservableCollection<string>();
private string _currentChannel;
private ObservableCollection<ChatMessage> _messages = new ObservableCollection<ChatMessage>();
private string _selectedChannel;
private string _title;
private ICommand _toggleOptionCommand;
private bool _topmost = true;
private ObservableCollection<ChatUser> _users = new ObservableCollection<ChatUser>();
public ChatViewModel()
{
_manager = ChatManager.GetInstance();
_manager.UserJoinedEvent += OnUserJoined;
_manager.UserLeftEvent += OnUserLeft;
_manager.ClearUsersEvent += OnClearUsers;
_manager.JoinedChatChannelEvent += OnJoinedChatChannel;
_manager.LeftChatChannelEvent += OnLeftChatChannel;
Engine.DisconnectedEvent += () => OnLeftChatChannel( string.Empty );
_manager.ChannelCreatedEvent += OnChannelCreated;
_manager.ChannelRemovedEvent += OnChannelRemoved;
if ( !string.IsNullOrEmpty( _manager.CurrentChannel ) )
{
OnJoinedChatChannel( _manager.CurrentChannel );
}
else
{
UpdateTitle( Strings.Chat );
}
foreach ( string user in _manager.Users )
{
//TODO2
Users.AddSorted( new ChatUser { Username = user/*, Colour = GetUserColour( user )*/ } );
}
foreach ( string channel in _manager.Channels )
{
OnChannelCreated( channel );
}
//foreach ( ChatMessage message in _manager.Messages )
//{
// Messages.Add( message );
//}
_manager.ChatMessageEvent += OnChatMessage;
}
public ICommand ChangeChannelCommand =>
_changeChannelCommand ??
( _changeChannelCommand = new RelayCommand( ChangeChannel, o => Channels.Count != 0 ) );
public ObservableCollection<string> Channels
{
get => _channels;
set => SetProperty( ref _channels, value );
}
public string CurrentChannel
{
get => _currentChannel;
set => SetProperty( ref _currentChannel, value );
}
public ObservableCollection<ChatMessage> Messages
{
get => _messages;
set => SetProperty( ref _messages, value );
}
public string SelectedChannel
{
get => _selectedChannel;
set => SetProperty( ref _selectedChannel, value );
}
public string Title
{
get => _title;
set => SetProperty( ref _title, value );
}
public ICommand ToggleOptionCommand =>
_toggleOptionCommand ?? ( _toggleOptionCommand = new RelayCommand( ToggleOption, o => true ) );
public bool Topmost
{
get => _topmost;
set => SetProperty( ref _topmost, value );
}
public ObservableCollection<ChatUser> Users
{
get => _users;
set => SetProperty( ref _users, value );
}
private static void ToggleOption( object obj )
{
}
private void ChangeChannel( object obj )
{
if ( !( obj is string channel ) )
{
return;
}
_dispatcher.Invoke( () => { Commands.JoinChatChannel( channel ); } );
}
private void OnChannelRemoved( string channel )
{
_dispatcher.Invoke( () => { Channels.Remove( channel ); } );
}
private void OnChannelCreated( string channel )
{
_dispatcher.Invoke( () => { Channels.Add( channel ); } );
}
private void OnChatMessage( string username, string channel, string message )
{
_dispatcher.Invoke( () => Messages.Add( new ChatMessage
{
//TODO2
Username = username,
Channel = channel,
Text = message/*, Colour = GetUserColour( username )*/
} ) );
}
private void OnLeftChatChannel( string channel )
{
_dispatcher.Invoke( () =>
{
Users.Clear();
CurrentChannel = null;
SelectedChannel = null;
UpdateTitle( string.Empty );
} );
}
private void UpdateTitle( string channel )
{
if ( string.IsNullOrEmpty( channel ) )
{
Title = Strings.Chat;
return;
}
Title = $"{Strings.Chat} - {channel}";
}
private void OnJoinedChatChannel( string channel )
{
_dispatcher.Invoke( () =>
{
CurrentChannel = channel;
SelectedChannel = channel;
UpdateTitle( channel );
} );
}
private void OnClearUsers()
{
_dispatcher.Invoke( () => Users.Clear() );
}
private void OnUserLeft( string username, string channel )
{
_dispatcher.Invoke( () => { Users.Remove( Users.FirstOrDefault( u => u.Username == username ) ); } );
}
private void OnUserJoined( string username, string channel )
{
_dispatcher.Invoke( () =>
{
//TODO2
ChatUser user = new ChatUser { Username = username/*, Colour = GetUserColour( username )*/ };
Users.AddSorted( user );
} );
}
private SolidColorBrush GetUserColour( string username )
{
try
{
Match matches = Regex.Match( username, @"<(.*)>\s*(.*)" );
if ( !matches.Success )
{
return _defaultBrush;
}
int serial = int.Parse( matches.Groups[1].Value );
if ( serial == Engine.Player?.Serial || MobileCommands.InFriendList( serial ) )
{
return _friendBrush;
}
return serial == AliasCommands.GetAlias( "enemy" ) ? _enemyBrush : _defaultBrush;
}
catch ( Exception )
{
return _defaultBrush;
}
}
}
}
@@ -0,0 +1,129 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using ClassicAssist.Shared;
using ClassicAssist.Data;
using ClassicAssist.Shared.Resources;
using Microsoft.Win32;
namespace ClassicAssist.UI.ViewModels.Debug
{
public class DebugAssembliesViewModel : BaseViewModel
{
private ObservableCollection<Assembly> _items = new ObservableCollection<Assembly>();
private ICommand _loadCommand;
private ICommand _removeCommand;
private ICommand _saveCommand;
public DebugAssembliesViewModel()
{
if ( AssistantOptions.Assemblies == null )
{
return;
}
foreach ( string assemblyName in AssistantOptions.Assemblies )
{
Assembly assembly = LoadAssembly( assemblyName );
if ( assembly != null )
{
Items.Add( assembly );
}
}
}
public ObservableCollection<Assembly> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public ICommand LoadCommand => _loadCommand ?? ( _loadCommand = new RelayCommandAsync( Load, o => true ) );
public ICommand RemoveCommand =>
_removeCommand ?? ( _removeCommand = new RelayCommandAsync( Remove, o => true ) );
public ICommand SaveCommand => _saveCommand ?? ( _saveCommand = new RelayCommandAsync( Save, o => true ) );
public Assembly SelectedItem { get; set; }
private async Task Load( object arg )
{
OpenFileDialog ofd = new OpenFileDialog
{
InitialDirectory = Engine.StartupPath, Filter = "DLL Files|*.dll", CheckFileExists = true
};
bool? result = ofd.ShowDialog();
if ( result.HasValue && result.Value )
{
try
{
Assembly assembly = LoadAssembly( ofd.FileName );
if ( assembly != null )
{
await _dispatcher.InvokeAsync( () => Items.Add( assembly ) );
}
}
catch ( Exception e )
{
MessageBox.Show( string.Format( Strings.Error_loading_assembly___0_, e.Message ) );
}
}
}
private static Assembly LoadAssembly( string fileName )
{
if ( !File.Exists( fileName ) )
{
return null;
}
return Assembly.LoadFile( fileName );
}
private async Task Remove( object arg )
{
if ( !( arg is Assembly assembly ) )
{
return;
}
await _dispatcher.InvokeAsync( () => Items.Remove( assembly ) );
}
private async Task Save( object arg )
{
AssistantOptions.Assemblies = Items.Select( a => a.Location ).ToArray();
await Task.CompletedTask;
}
}
}
@@ -0,0 +1,620 @@
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 System.Windows.Media.Imaging;
using ClassicAssist.Shared;
using ClassicAssist.Data.Autoloot;
using ClassicAssist.Data.Macros.Commands;
using ClassicAssist.Misc;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UI.Models;
using ClassicAssist.UI.Views;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Network;
using ClassicAssist.UO.Network.Packets;
using ClassicAssist.UO.Objects;
using Newtonsoft.Json;
namespace ClassicAssist.UI.ViewModels
{
public class EntityCollectionViewerViewModel : BaseViewModel
{
private ICommand _applyFiltersCommand;
private ICommand _cancelActionCommand;
private CancellationTokenSource _cancellationToken;
private ICommand _changeSortStyleCommand;
private ItemCollection _collection;
private ICommand _contextContextMenuRequestCommand;
private ICommand _contextMoveToBackpackCommand;
private ICommand _contextMoveToContainerCommand;
private ICommand _contextUseItemCommand;
private ObservableCollection<EntityCollectionData> _entities;
private ICommand _equipItemCommand;
private IEnumerable<EntityCollectionFilter> _filters;
private bool _isPerformingAction;
private ICommand _itemDoubleClickCommand;
private ICommand _refreshCommand;
private ObservableCollection<EntityCollectionData> _selectedItems =
new ObservableCollection<EntityCollectionData>();
private bool _showProperties;
private IComparer<Entity> _sorter = new IDThenSerialComparer();
private string _statusLabel;
private ICommand _togglePropertiesCommand;
private bool _topmost;
public EntityCollectionViewerViewModel()
{
_collection = new ItemCollection( 0 );
for ( int i = 0; i < 5; i++ )
{
_collection.Add( new Item( i + 1 ) { ID = 100 + i } );
}
_collection.Add( new Item( 6 ) { ID = 106, Hue = 2413 } );
Entities = new ObservableCollection<EntityCollectionData>( _collection.ToEntityCollectionData( _sorter ) );
}
public EntityCollectionViewerViewModel( ItemCollection collection )
{
_collection = collection;
Entities = new ObservableCollection<EntityCollectionData>( collection.ToEntityCollectionData( _sorter ) );
SelectedItems.CollectionChanged += ( sender, args ) =>
{
if ( !( sender is ObservableCollection<EntityCollectionData> ) )
{
return;
}
UpdateStatusLabel();
};
UpdateStatusLabel();
}
public ICommand ApplyFiltersCommand =>
_applyFiltersCommand ?? ( _applyFiltersCommand = new RelayCommand( ApplyFilters, o => true ) );
public ICommand CancelActionCommand =>
_cancelActionCommand ?? ( _cancelActionCommand = new RelayCommandAsync( CancelAction,
o => _cancellationToken != null ) );
public ICommand ChangeSortStyleCommand =>
_changeSortStyleCommand ?? ( _changeSortStyleCommand = new RelayCommand( ChangeSortStyle, o => true ) );
public ICommand ContextContextMenuRequestCommand =>
_contextContextMenuRequestCommand ?? ( _contextContextMenuRequestCommand =
new RelayCommand( ContextMenuRequest, o => SelectedItems.Count > 0 ) );
public ICommand ContextMoveToBackpackCommand =>
_contextMoveToBackpackCommand ?? ( _contextMoveToBackpackCommand =
new RelayCommandAsync( ContextMoveToBackpack, o => SelectedItems != null && !IsPerformingAction ) );
public ICommand ContextMoveToContainerCommand =>
_contextMoveToContainerCommand ?? ( _contextMoveToContainerCommand =
new RelayCommandAsync( ContextMoveToContainer, o => SelectedItems != null && !IsPerformingAction ) );
public ICommand ContextUseItemCommand =>
_contextUseItemCommand ?? ( _contextUseItemCommand =
new RelayCommandAsync( ContextUseItem, o => SelectedItems != null && !IsPerformingAction ) );
public ObservableCollection<EntityCollectionData> Entities
{
get => _entities;
set => SetProperty( ref _entities, value );
}
public ICommand EquipItemCommand =>
_equipItemCommand ?? ( _equipItemCommand = new RelayCommand( EquipItem, o => SelectedItems != null ) );
public bool IsPerformingAction
{
get => _isPerformingAction;
set => SetProperty( ref _isPerformingAction, value );
}
public ICommand ItemDoubleClickCommand =>
_itemDoubleClickCommand ?? ( _itemDoubleClickCommand = new RelayCommand( ItemDoubleClick, o => true ) );
public static Lazy<Dictionary<int, int>> MountIDEntries { get; set; } =
new Lazy<Dictionary<int, int>>( LoadMountIDEntries );
public ICommand RefreshCommand =>
_refreshCommand ?? ( _refreshCommand = new RelayCommand( Refresh, o => _collection?.Serial != 0 ) );
public ObservableCollection<EntityCollectionData> SelectedItems
{
get => _selectedItems;
set => SetProperty( ref _selectedItems, value );
}
public bool ShowProperties
{
get => _showProperties;
set => SetProperty( ref _showProperties, value );
}
public static Lazy<int[]> ShrinkEntries { get; set; } = new Lazy<int[]>( LoadShrinkTable );
public string StatusLabel
{
get => _statusLabel;
set => SetProperty( ref _statusLabel, value );
}
public ICommand TogglePropertiesCommand =>
_togglePropertiesCommand ?? ( _togglePropertiesCommand = new RelayCommand( ToggleProperties, o => true ) );
public bool Topmost
{
get => _topmost;
set => SetProperty( ref _topmost, value );
}
private static Dictionary<int, int> LoadMountIDEntries()
{
Dictionary<int, int> entries = new Dictionary<int, int>();
string fileName = Path.Combine( Engine.StartupPath, "Data", "MountID.json" );
if ( !File.Exists( fileName ) )
{
return entries;
}
try
{
entries = JsonConvert.DeserializeObject<Dictionary<int, int>>( File.ReadAllText( fileName ) );
}
catch ( Exception )
{
// ignored
}
return entries;
}
private static int[] LoadShrinkTable()
{
int[] table = new int[ushort.MaxValue];
using ( StringReader reader = new StringReader( Properties.Resources.Shrink ) )
{
string line;
while ( ( line = reader.ReadLine() ) != null )
{
if ( line.Length == 0 || line.StartsWith( "#" ) )
{
continue;
}
string[] split = line.Split( '\t' );
if ( split.Length < 2 )
{
continue;
}
int body = Convert.ToInt32( split[0] );
int item = Convert.ToInt32( split[1], 16 );
if ( body >= 0 && body < table.Length )
{
table[body] = item;
}
}
}
return table;
}
private void EquipItem( object obj )
{
foreach ( EntityCollectionData item in SelectedItems )
{
StaticTile td = TileData.GetStaticTile( item.Entity.ID );
if ( !td.Flags.HasFlag( TileFlags.Wearable ) )
{
continue;
}
Layer layer = (Layer) td.Quality;
if ( layer == Layer.Invalid )
{
continue;
}
if ( item.Entity is Item equipItem )
{
Shared.UO.Commands.EquipItem( equipItem, layer );
}
}
}
private void ApplyFilters( object obj )
{
if ( !( obj is IEnumerable<EntityCollectionFilter> list ) )
{
return;
}
_filters = list;
Entities.Clear();
Entities = new ObservableCollection<EntityCollectionData>( _collection.Filter( _filters )
.ToEntityCollectionData( _sorter ) );
UpdateStatusLabel();
}
private void ChangeSortStyle( object obj )
{
if ( !( obj is EntityCollectionSortStyle val ) )
{
return;
}
switch ( val )
{
case EntityCollectionSortStyle.Name:
_sorter = new NameThenSerialComparer();
break;
case EntityCollectionSortStyle.Serial:
_sorter = new SerialComparer();
break;
case EntityCollectionSortStyle.Hue:
_sorter = new HueThenAmountComparer();
break;
case EntityCollectionSortStyle.ID:
_sorter = new IDThenSerialComparer();
break;
case EntityCollectionSortStyle.Quantity:
_sorter = new QuantityThenSerialComparer();
break;
default:
throw new ArgumentOutOfRangeException();
}
Entities = new ObservableCollection<EntityCollectionData>( _collection.ToEntityCollectionData( _sorter ) );
}
private void UpdateStatusLabel()
{
StatusLabel = string.Format( Strings._0__items___1__selected___2__total_amount, Entities.Count,
SelectedItems?.Count ?? 0,
SelectedItems?.Select( i => i.Entity ).Where( i => i is Item ).Cast<Item>().Sum( i => i.Count ) );
}
private void Refresh( object obj )
{
ItemCollection collection = new ItemCollection( _collection.Serial );
Entity entity = Engine.Items.GetItem( _collection.Serial ) ??
(Entity) Engine.Mobiles.GetMobile( _collection.Serial );
if ( entity == null )
{
Shared.UO.Commands.SystemMessage( Strings.Cannot_find_item___ );
return;
}
switch ( entity )
{
case Item item:
if ( item.Container == null )
{
Shared.UO.Commands.WaitForContainerContents( item.Serial, 1000 );
}
collection = item.Container;
break;
case Mobile mobile:
collection = new ItemCollection( entity.Serial ) { mobile.GetEquippedItems() };
break;
}
if ( collection == null )
{
return;
}
_collection = collection;
Entities = new ObservableCollection<EntityCollectionData>( _collection.ToEntityCollectionData( _sorter ) );
}
private async Task ContextUseItem( object arg )
{
_cancellationToken = new CancellationTokenSource();
try
{
IsPerformingAction = true;
await Task.Run( () =>
{
int[] items = SelectedItems.Select( i => i.Entity.Serial ).ToArray();
foreach ( int item in items )
{
ObjectCommands.UseObject( item );
if ( _cancellationToken.Token.IsCancellationRequested )
{
return;
}
}
} );
}
finally
{
IsPerformingAction = false;
}
}
private async Task ContextMoveToContainer( object arg )
{
_cancellationToken = new CancellationTokenSource();
int serial = 0;
if ( arg is int s )
{
serial = s;
}
if ( serial == 0 )
{
serial = await Shared.UO.Commands.GetTargeSerialAsync( Strings.Target_container___ );
}
if ( serial == 0 )
{
Shared.UO.Commands.SystemMessage( Strings.Invalid_container___ );
return;
}
try
{
IsPerformingAction = true;
int[] items = SelectedItems.Select( i => i.Entity.Serial ).ToArray();
foreach ( int item in items )
{
await ActionPacketQueue.EnqueueDragDrop( item, -1, serial );
if ( _cancellationToken.Token.IsCancellationRequested )
{
return;
}
}
}
finally
{
IsPerformingAction = false;
}
}
private async Task ContextMoveToBackpack( object arg )
{
await ContextMoveToContainer( Engine.Player.Backpack.Serial );
}
private async Task CancelAction( object arg )
{
_cancellationToken?.Cancel();
await Task.CompletedTask;
}
private void ToggleProperties( object obj )
{
if ( !( obj is bool showProperties ) )
{
return;
}
ShowProperties = showProperties;
}
private static void ItemDoubleClick( object obj )
{
if ( !( obj is EntityCollectionData ecd ) )
{
return;
}
ObjectInspectorWindow window =
new ObjectInspectorWindow { DataContext = new ObjectInspectorViewModel( ecd.Entity ) };
window.ShowDialog();
}
private void ContextMenuRequest( object obj )
{
int[] items = SelectedItems.Select( i => i.Entity.Serial ).ToArray();
foreach ( int serial in items )
{
Engine.SendPacketToServer( new ContextMenuRequest( serial ) );
}
}
}
public class EntityCollectionData
{
public BitmapSource Bitmap
{
get
{
BitmapSource result = Art.GetStatic( Entity.ID, Entity.Hue ).ToBitmapSource();
if ( !( Entity is Item item ) || item.Layer != Layer.Mount )
{
return result;
}
if ( !( EntityCollectionViewerViewModel.MountIDEntries.Value?.ContainsKey( Entity.ID ) ?? false ) )
{
return result;
}
int id = (int) EntityCollectionViewerViewModel.MountIDEntries.Value?[Entity.ID];
result = Art.GetStatic( id, Entity.Hue ).ToBitmapSource();
return result;
}
}
public Entity Entity { get; set; }
public string FullName => GetProperties( Entity );
public string Name => GetName( Entity );
private static string GetProperties( Entity entity )
{
return entity.Properties == null
? GetName( entity )
: entity.Properties.Aggregate( "",
( current, entityProperty ) => current + entityProperty.Text + "\r\n" ).TrimTrailingNewLine();
}
private static string GetName( Entity entity )
{
if ( !( entity is Item item ) || item.Layer != Layer.Mount )
{
return entity.Name;
}
if ( !( EntityCollectionViewerViewModel.MountIDEntries.Value?.ContainsKey( entity.ID ) ?? false ) )
{
return entity.Name;
}
int id = (int) EntityCollectionViewerViewModel.MountIDEntries.Value?[entity.ID];
if ( id == 0 )
{
return entity.Name;
}
StaticTile tileData = TileData.GetStaticTile( id );
return !string.IsNullOrEmpty( tileData.Name ) ? tileData.Name : entity.Name;
}
}
public static class ExtensionMethods
{
public static ItemCollection Filter( this ItemCollection collection,
IEnumerable<EntityCollectionFilter> filterList )
{
ItemCollection newCollection = new ItemCollection( collection.Serial );
IEnumerable<Predicate<Item>> predicates = FiltersToPredicates( filterList ).ToList();
if ( !predicates.Any() )
{
return collection;
}
foreach ( Item item in collection.GetItems() )
{
if ( predicates.All( p => p( item ) ) )
{
newCollection.Add( item );
}
}
return newCollection;
}
private static IEnumerable<Predicate<Item>> FiltersToPredicates(
IEnumerable<EntityCollectionFilter> filterList )
{
List<Predicate<Item>> predicates = new List<Predicate<Item>>();
foreach ( EntityCollectionFilter filter in filterList )
{
PropertyEntry constraint = filter.Constraint;
switch ( constraint.ConstraintType )
{
case PropertyType.Properties:
{
predicates.Add( i => i.Properties != null && constraint.Clilocs.Any( cliloc =>
i.Properties.Any( p => AutolootHelpers.MatchProperty( p, cliloc,
constraint, filter.Operator, filter.Value ) ) ) );
break;
}
case PropertyType.Object:
{
predicates.Add( i =>
AutolootHelpers.ItemHasObjectProperty( i, constraint.Name ) && AutolootHelpers.Operation(
filter.Operator, AutolootHelpers.GetItemObjectPropertyValue<int>( i, constraint.Name ),
filter.Value ) );
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
return predicates;
}
public static string TrimTrailingNewLine( this string s )
{
return s.TrimEnd( '\r', '\n' );
}
public static List<EntityCollectionData> ToEntityCollectionData( this ItemCollection itemCollection,
IComparer<Entity> comparer )
{
if ( itemCollection == null )
{
return new List<EntityCollectionData>();
}
Item[] items = itemCollection.GetItems();
IEnumerable<Item> noNames = items.Where( i => string.IsNullOrEmpty( i.Name ) );
foreach ( Item item in noNames )
{
item.Name = $"0x{item.Serial:x8}";
}
return items.OrderBy( i => i, comparer ).Select( item => new EntityCollectionData { Entity = item } )
.ToList();
}
}
}
@@ -0,0 +1,148 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using ClassicAssist.Data.Filters;
using ClassicAssist.UO.Data;
namespace ClassicAssist.UI.ViewModels.Filters
{
public class ClilocFilterConfigureViewModel : BaseViewModel
{
private ICommand _addItemCommand;
private ObservableCollection<ClilocEntry> _allClilocs = new ObservableCollection<ClilocEntry>();
private ObservableCollection<ClilocEntry> _filteredClilocs = new ObservableCollection<ClilocEntry>();
private string _filterText;
private ObservableCollection<FilterClilocEntry> _items = new ObservableCollection<FilterClilocEntry>();
private ICommand _removeItemCommand;
private ICommand _saveItemsCommand;
private ClilocEntry _selectedClilocEntry;
private FilterClilocEntry _selectedItem;
public ClilocFilterConfigureViewModel()
{
foreach ( KeyValuePair<int, string> kvp in Cliloc.GetItems() )
{
AllClilocs.Add( new ClilocEntry { Key = kvp.Key, Value = kvp.Value } );
}
foreach ( KeyValuePair<int, string> filterFilter in ClilocFilter.Filters )
{
Items.Add( new FilterClilocEntry { Cliloc = filterFilter.Key, Replacement = filterFilter.Value } );
}
UpdateEntries( _filterText );
}
public ICommand AddItemCommand => _addItemCommand ?? ( _addItemCommand = new RelayCommand( AddItem ) );
public ObservableCollection<ClilocEntry> AllClilocs
{
get => _allClilocs;
set => SetProperty( ref _allClilocs, value );
}
public ObservableCollection<ClilocEntry> FilteredClilocs
{
get => _filteredClilocs;
set => SetProperty( ref _filteredClilocs, value );
}
public string FilterText
{
get => _filterText;
set
{
SetProperty( ref _filterText, value );
UpdateEntries( _filterText );
}
}
public ObservableCollection<FilterClilocEntry> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public ICommand RemoveItemCommand =>
_removeItemCommand ?? ( _removeItemCommand = new RelayCommand( RemoveItem, o => SelectedItem != null ) );
public ICommand SaveItemsCommand =>
_saveItemsCommand ?? ( _saveItemsCommand = new RelayCommand( SaveItems, o => true ) );
public ClilocEntry SelectedClilocEntry
{
get => _selectedClilocEntry;
set => SetProperty( ref _selectedClilocEntry, value );
}
public FilterClilocEntry SelectedItem
{
get => _selectedItem;
set => SetProperty( ref _selectedItem, value );
}
private void RemoveItem( object obj )
{
if ( !( obj is FilterClilocEntry entry ) )
{
return;
}
Items.Remove( entry );
}
private void SaveItems( object obj )
{
ClilocFilter.Filters.Clear();
foreach ( FilterClilocEntry entry in Items )
{
if ( !ClilocFilter.Filters.ContainsKey( entry.Cliloc ) )
{
ClilocFilter.Filters.Add( entry.Cliloc, entry.Replacement );
}
}
}
private void UpdateEntries( string filterText )
{
IEnumerable<ClilocEntry> matches = AllClilocs.Where( m =>
string.IsNullOrEmpty( filterText ) || m.Value.ToLower().Contains( filterText.ToLower() ) );
FilteredClilocs.Clear();
foreach ( ClilocEntry clilocEntry in matches )
{
FilteredClilocs.Add( clilocEntry );
}
}
private void AddItem( object obj )
{
if ( !( obj is ClilocEntry clilocEntry ) )
{
return;
}
if ( Items.Any( i => i.Cliloc == clilocEntry.Key ) )
{
return;
}
Items.Add( new FilterClilocEntry { Cliloc = clilocEntry.Key, Replacement = clilocEntry.Value } );
}
public class ClilocEntry
{
public int Key { get; set; }
public string Value { get; set; }
}
public class FilterClilocEntry
{
public int Cliloc { get; set; }
public string Original => UO.Data.Cliloc.GetProperty( Cliloc );
public string Replacement { get; set; }
}
}
}
@@ -0,0 +1,171 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Threading;
using AnimatedGif;
using ClassicAssist.Shared;
using ClassicAssist.UI.Views;
using Point = System.Drawing.Point;
using Size = System.Drawing.Size;
namespace ClassicAssist.UI.ViewModels
{
public class GIFRecorderViewModel : BaseViewModel
{
private readonly GIFRecorderWindow _window;
private bool _isRecording;
private MemoryStream _lastStream;
private ICommand _recordCommand;
private ICommand _saveCommand;
private CancellationTokenSource _token;
public GIFRecorderViewModel( GIFRecorderWindow window ) : this()
{
_window = window;
}
public GIFRecorderViewModel()
{
}
public bool IsRecording
{
get => _isRecording;
set => SetProperty( ref _isRecording, value );
}
public MemoryStream LastStream
{
get => _lastStream;
set => SetProperty( ref _lastStream, value );
}
public ICommand RecordCommand => _recordCommand ?? ( _recordCommand = new RelayCommand( Record, o => true ) );
public ICommand SaveCommand => _saveCommand ?? ( _saveCommand = new RelayCommand( Save, o => !IsRecording ) );
private void Save( object obj )
{
if ( LastStream == null )
{
return;
}
string directory = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Screenshots" );
if ( !Directory.Exists( directory ) )
{
Directory.CreateDirectory( directory );
}
DateTime now = DateTime.Now;
string fileName =
$"ClassicAssist-{now.Year}-{now.Month}-{now.Day}-{now.Hour}-{now.Minute}-{now.Second}.gif";
string fullPath = Path.Combine( directory, fileName );
using ( FileStream fs = new FileStream( fullPath, FileMode.Create ) )
{
LastStream.WriteTo( fs );
}
string args = $"/e, /select, \"{fullPath}\"";
ProcessStartInfo info = new ProcessStartInfo { FileName = "explorer", Arguments = args };
Process.Start( info );
}
private void Record( object obj )
{
if ( IsRecording )
{
_token.Cancel();
}
else
{
IsRecording = true;
_token = new CancellationTokenSource();
Window w = Window.GetWindow( _window );
WindowInteropHelper wih = new WindowInteropHelper( w ?? throw new InvalidOperationException() );
Task.Run( async () =>
{
try
{
TimeSpan frameInterval = TimeSpan.FromSeconds( 1.0 / 5 );
MemoryStream ms = new MemoryStream();
using ( AnimatedGifCreator gif = new AnimatedGifCreator( ms, frameInterval.Milliseconds ) )
{
Rectangle rect = new Rectangle();
_dispatcher.Invoke( () => GetWindowRect( wih.Handle, ref rect ) );
Bitmap bmp = new Bitmap( rect.Width - rect.Left - 10, rect.Height - rect.Top - 70 );
Stopwatch sw = new Stopwatch();
sw.Start();
while ( true )
{
_dispatcher.Invoke( () => GetWindowRect( wih.Handle, ref rect ) );
using ( Graphics g = Graphics.FromImage( bmp ) )
{
g.CopyFromScreen( new Point( rect.Left + 5, rect.Top + 50 ), Point.Empty,
new Size( bmp.Width, bmp.Height ) );
}
await gif.AddFrameAsync( bmp, -1, GifQuality.Bit8 );
sw.Stop();
int wait = frameInterval.Milliseconds - (int) sw.ElapsedMilliseconds;
if ( wait > 0 )
{
await Task.Delay( wait );
}
if ( _token.IsCancellationRequested )
{
return ms;
}
}
}
}
finally
{
_dispatcher.Invoke( () => IsRecording = false );
}
} ).ContinueWith( t =>
{
if ( !( t.Result is MemoryStream ms ) )
{
return;
}
if ( LastStream != null )
{
LastStream.Dispose();
LastStream = null;
}
LastStream = ms;
CommandManager.InvalidateRequerySuggested();
} );
}
}
[DllImport( "user32.dll" )]
private static extern IntPtr GetWindowRect( IntPtr hWnd, ref Rectangle rect );
}
}
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Windows.Input;
using ClassicAssist.Data.Macros;
namespace ClassicAssist.UI.ViewModels.Macros
{
public class CommandsData
{
public CommandsDisplayAttribute Attribute { get; set; }
public string Category { get; set; }
public bool IsExpanded { get; set; }
public string Name { get; set; }
public string Tooltip { get; set; }
public override string ToString()
{
return Name;
}
}
public class MacrosCommandViewModel : BaseViewModel
{
private readonly MacrosTabViewModel _macrosViewModel;
private ICommand _insertCommand;
private ObservableCollection<CommandsData> _items = new ObservableCollection<CommandsData>();
private CommandsData _selectedItem;
public MacrosCommandViewModel( MacrosTabViewModel macros ) : this()
{
_macrosViewModel = macros;
}
public MacrosCommandViewModel()
{
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes().Where( t =>
t.Namespace != null && t.Namespace.StartsWith( "ClassicAssist.Data.Macros.Commands" ) );
foreach ( Type type in types )
{
MemberInfo[] members = type.GetMembers( BindingFlags.Public | BindingFlags.Static );
foreach ( MemberInfo memberInfo in members )
{
CommandsDisplayAttribute attr = memberInfo.GetCustomAttribute<CommandsDisplayAttribute>();
if ( attr == null )
{
continue;
}
CommandsData entry = new CommandsData
{
Category = attr.Category,
IsExpanded = false,
Name = memberInfo.ToString(),
Tooltip = attr.Description,
Attribute = attr
};
Items.Add( entry );
}
}
}
public ICommand InsertCommand =>
_insertCommand ?? ( _insertCommand = new RelayCommand( Insert, o => SelectedItem != null ) );
public ObservableCollection<CommandsData> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public CommandsData SelectedItem
{
get => _selectedItem;
set => SetProperty( ref _selectedItem, value );
}
private void Insert( object obj )
{
if ( !( obj is CommandsData cd ) )
{
return;
}
if ( cd.Attribute != null )
{
//TODO UI
//_macrosViewModel?.Document.Insert( _macrosViewModel.CaretPosition, cd.Attribute.InsertText );
}
}
}
}