198 lines
5.7 KiB
C#
198 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Input;
|
|
using ClassicAssist.Launcher.Properties;
|
|
|
|
namespace ClassicAssist.Launcher
|
|
{
|
|
public class ShardsViewModel : BaseViewModel
|
|
{
|
|
private readonly ShardManager _manager;
|
|
private ICommand _addCommand;
|
|
private ICommand _cancelCommand;
|
|
private bool _isRefreshing;
|
|
private ICommand _okCommand;
|
|
private ICommand _refreshCommand;
|
|
private ICommand _removeCommand;
|
|
private ShardEntry _selectedShard;
|
|
private ObservableCollection<ShardEntry> _shards;
|
|
|
|
public ShardsViewModel()
|
|
{
|
|
_manager = ShardManager.GetInstance();
|
|
Shards = _manager.Shards;
|
|
|
|
Refresh( this );
|
|
}
|
|
|
|
public ICommand AddCommand => _addCommand ?? ( _addCommand = new RelayCommand( Add, o => true ) );
|
|
|
|
public ICommand CancelCommand => _cancelCommand ?? ( _cancelCommand = new RelayCommand( Cancel, o => true ) );
|
|
|
|
public DialogResult DialogResult { get; set; }
|
|
|
|
public bool IsRefreshing
|
|
{
|
|
get => _isRefreshing;
|
|
set => SetProperty( ref _isRefreshing, value );
|
|
}
|
|
|
|
public ICommand OKCommand => _okCommand ?? ( _okCommand = new RelayCommand( OK, o => true ) );
|
|
|
|
public ICommand RefreshCommand =>
|
|
_refreshCommand ?? ( _refreshCommand = new RelayCommand( Refresh, o => !IsRefreshing ) );
|
|
|
|
public ICommand RemoveCommand =>
|
|
_removeCommand ?? ( _removeCommand =
|
|
new RelayCommand( Remove, o => SelectedShard != null && !SelectedShard.IsPreset ) );
|
|
|
|
public ShardEntry SelectedShard
|
|
{
|
|
get => _selectedShard;
|
|
set => SetProperty( ref _selectedShard, value );
|
|
}
|
|
|
|
public ObservableCollection<ShardEntry> Shards
|
|
{
|
|
get => _shards;
|
|
set
|
|
{
|
|
SetProperty( ref _shards, value );
|
|
_manager.Shards = value;
|
|
}
|
|
}
|
|
|
|
private void Remove( object obj )
|
|
{
|
|
if ( !( obj is ShardEntry entry ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( entry.IsPreset )
|
|
{
|
|
MessageBox.Show( Resources.Cannot_remove_preset_shard, Resources.Error );
|
|
return;
|
|
}
|
|
|
|
Shards.Remove( entry );
|
|
}
|
|
|
|
private void Add( object obj )
|
|
{
|
|
Shards.Add( new ShardEntry { Name = "Shard Name", Address = "localhost", Port = 2593 } );
|
|
}
|
|
|
|
private void Refresh( object obj )
|
|
{
|
|
try
|
|
{
|
|
foreach ( ShardEntry shard in Shards )
|
|
{
|
|
Task.Run( async () =>
|
|
{
|
|
if ( !shard.HasStatusProtocol )
|
|
{
|
|
return "-";
|
|
}
|
|
|
|
string status = await GetStatus( shard );
|
|
|
|
return status;
|
|
} ).ContinueWith( t =>
|
|
{
|
|
if ( !string.IsNullOrEmpty( shard.StatusRegex ) )
|
|
{
|
|
Match matches = Regex.Match( t.Result, shard.StatusRegex );
|
|
|
|
shard.Status = matches.Success ? matches.Groups[1].Value : "-";
|
|
}
|
|
else
|
|
{
|
|
shard.Status = t.Result;
|
|
}
|
|
|
|
NotifyPropertyChanged( nameof( Shards ) );
|
|
} );
|
|
|
|
Task.Run( async () => await GetPing( shard ) ).ContinueWith( result =>
|
|
{
|
|
shard.Ping = result.Result;
|
|
NotifyPropertyChanged( nameof( Shards ) );
|
|
} );
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
IsRefreshing = false;
|
|
}
|
|
}
|
|
|
|
private void OK( object obj )
|
|
{
|
|
DialogResult = DialogResult.OK;
|
|
}
|
|
|
|
public async Task<string> GetStatus( ShardEntry shard )
|
|
{
|
|
if ( !shard.HasStatusProtocol )
|
|
{
|
|
return "Unknown";
|
|
}
|
|
|
|
TcpClient client = new TcpClient();
|
|
|
|
Task connectTask = client.ConnectAsync( shard.Address, shard.Port );
|
|
|
|
await Task.WhenAny( connectTask, Task.Delay( TimeSpan.FromSeconds( 5 ) ) );
|
|
|
|
if ( !client.Connected )
|
|
{
|
|
return "Unknown";
|
|
}
|
|
|
|
byte[] packet = { 0x7F, 0x00, 0x00, 0x7F, 0xF1, 0x00, 0x04, 0xFF };
|
|
client.Client.Send( packet );
|
|
|
|
NetworkStream stream = client.GetStream();
|
|
byte[] buffer = new byte[256];
|
|
|
|
stream.ReadTimeout = 60000;
|
|
await stream.ReadAsync( buffer, 0, buffer.Length );
|
|
|
|
client.Close();
|
|
|
|
string status = Encoding.ASCII.GetString( buffer ).TrimEnd( '\0' );
|
|
|
|
return status;
|
|
}
|
|
|
|
public async Task<string> GetPing( ShardEntry entry )
|
|
{
|
|
IPAddress ip = await Utility.ResolveAddress( entry.Address );
|
|
|
|
if ( ip == null )
|
|
{
|
|
return "-";
|
|
}
|
|
|
|
Ping ping = new Ping();
|
|
|
|
PingReply result = ping.Send( ip.ToString() );
|
|
|
|
return result?.Status == IPStatus.Success ? result.RoundtripTime.ToString() : "-";
|
|
}
|
|
|
|
private void Cancel( object obj )
|
|
{
|
|
DialogResult = DialogResult.Cancel;
|
|
}
|
|
}
|
|
} |