Skip to content

Commit

Permalink
[Shell] Added option to start/stop world/auth server from within the …
Browse files Browse the repository at this point in the history
…editor
  • Loading branch information
BAndysc committed Aug 21, 2022
1 parent aaba540 commit 55bb290
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public interface IProcess
{
bool IsRunning { get; }
void Kill();
event Action<int>? OnExit;
}

[UniqueProvider]
Expand Down
Binary file added WoWDatabaseEditor/Icons/icon_pause_mono.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added WoWDatabaseEditor/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added WoWDatabaseEditor/Icons/icon_play_mono.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added WoWDatabaseEditor/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions WoWDatabaseEditor/Managers/StatusBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using WDE.Module.Attributes;
using WDE.MVVM;
using WoWDatabaseEditorCore.Services.ProblemsTool;
using WoWDatabaseEditorCore.Services.ServerExecutable;
using WoWDatabaseEditorCore.ViewModels;

namespace WoWDatabaseEditorCore.Managers
Expand All @@ -23,20 +24,25 @@ public partial class StatusBar : ObservableBase, IStatusBar
private readonly TasksViewModel tasksViewModel;
private readonly IMainThread mainThread;
private readonly IPersonalGuidRangeService guidRangeService;
private readonly IServerExecutableService serverExecutableService;
private readonly Lazy<IClipboardService> clipboardService;
private readonly Lazy<IMessageBoxService> messageBoxService;

public IServerExecutableService ServerExecutableService => serverExecutableService;

public StatusBar(Lazy<IDocumentManager> documentManager,
TasksViewModel tasksViewModel,
IEventAggregator eventAggregator,
IMainThread mainThread,
IPersonalGuidRangeService guidRangeService,
IServerExecutableService serverExecutableService,
Lazy<IClipboardService> clipboardService,
Lazy<IMessageBoxService> messageBoxService)
{
this.tasksViewModel = tasksViewModel;
this.mainThread = mainThread;
this.guidRangeService = guidRangeService;
this.serverExecutableService = serverExecutableService;
this.clipboardService = clipboardService;
this.messageBoxService = messageBoxService;

Expand Down
9 changes: 9 additions & 0 deletions WoWDatabaseEditor/Services/Processes/ProcessService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ public class ProcessData : IProcess
public ProcessData(Process process)
{
this.process = process;
process.EnableRaisingEvents = true;
process.Exited += ProcessOnExited;
}

private void ProcessOnExited(object? sender, EventArgs e)
{
OnExit?.Invoke(process.ExitCode);
}

public bool IsRunning => !process.HasExited;
Expand All @@ -30,6 +37,8 @@ public void Kill()
process.Kill();
}
}

public event Action<int>? OnExit;
}

public IProcess RunAndForget(string path, string arguments, string? workingDirectory, bool noWindow,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using WDE.Module.Attributes;

namespace WoWDatabaseEditorCore.Services.ServerExecutable;

[UniqueProvider]
public interface IServerExecutableConfiguration
{
string? WorldServerPath { get; }
string? AuthServerPath { get; }
void Update(string? worldServerPath, string? authServerPath);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using AsyncAwaitBestPractices.MVVM;

namespace WoWDatabaseEditorCore.Services.ServerExecutable;

public interface IServerExecutableService
{
IAsyncCommand ToggleWorldServer { get; }
bool IsWorldServerRunning { get; }

IAsyncCommand ToggleAuthServer { get; }
bool IsAuthServerRunning { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using WDE.Common.Services;
using WDE.Module.Attributes;

namespace WoWDatabaseEditorCore.Services.ServerExecutable;

[SingleInstance]
[AutoRegister]
public class ServerExecutableConfiguration : IServerExecutableConfiguration
{
private readonly IUserSettings userSettings;
public string? WorldServerPath { get; set; }
public string? AuthServerPath { get; set; }

public ServerExecutableConfiguration(IUserSettings userSettings)
{
this.userSettings = userSettings;
var data = userSettings.Get<Data>();
WorldServerPath = data.WorldServerPath;
AuthServerPath = data.AuthServerPath;
}

public void Update(string? worldServerPath, string? authServerPath)
{
worldServerPath = string.IsNullOrWhiteSpace(worldServerPath) ? null : worldServerPath;
authServerPath = string.IsNullOrWhiteSpace(authServerPath) ? null : authServerPath;
WorldServerPath = worldServerPath;
AuthServerPath = authServerPath;
userSettings.Update(new Data(){WorldServerPath = worldServerPath, AuthServerPath = authServerPath});
}

private struct Data : ISettings
{
public string? WorldServerPath { get; set; }
public string? AuthServerPath { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Input;
using Prism.Commands;
using PropertyChanged.SourceGenerator;
using WDE.Common;
using WDE.Common.Managers;
using WDE.Common.Utils;
using WDE.Module.Attributes;
using WDE.MVVM;

namespace WoWDatabaseEditorCore.Services.ServerExecutable;

[AutoRegister]
public partial class ServerExecutableConfigurationPanelViewModel : ObservableBase, IConfigurable
{
private readonly IWindowManager windowManager;
private readonly IServerExecutableConfiguration configuration;
public ICommand Save { get; }
public string Name => "World server executable";
public string? ShortDescription => "You can configure your world and auth server paths for easy start/stop button access in the statusbar";
public bool IsRestartRequired => false;
public ConfigurableGroup Group => ConfigurableGroup.Advanced;

public bool IsModified => worldServerPath != configuration.WorldServerPath || authServerPath != configuration.AuthServerPath;
[Notify] [AlsoNotify(nameof(IsModified))] private string? worldServerPath;
[Notify] [AlsoNotify(nameof(IsModified))] private string? authServerPath;

public ICommand PickWorldPath { get; }
public ICommand PickAuthPath { get; }

public ServerExecutableConfigurationPanelViewModel(IWindowManager windowManager,
IServerExecutableConfiguration configuration)
{
this.windowManager = windowManager;
this.configuration = configuration;
worldServerPath = configuration.WorldServerPath;
authServerPath = configuration.AuthServerPath;
Save = new DelegateCommand(() =>
{
configuration.Update(worldServerPath, authServerPath);
RaisePropertyChanged(nameof(IsModified));
});

string filter = "All files|*";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
filter = "Windows executable|exe|All files|*";

PickWorldPath = new AsyncAutoCommand(async () =>
{
var path = await windowManager.ShowOpenFileDialog(filter, File.Exists(WorldServerPath) ? Directory.GetParent(WorldServerPath)?.FullName : null);
if (path != null && File.Exists(path))
WorldServerPath = path;
});

PickAuthPath = new AsyncAutoCommand(async () =>
{
var path = await windowManager.ShowOpenFileDialog(filter, File.Exists(AuthServerPath) ? Directory.GetParent(AuthServerPath)?.FullName : null);
if (path != null && File.Exists(path))
AuthServerPath = path;
});
}
}
119 changes: 119 additions & 0 deletions WoWDatabaseEditor/Services/ServerExecutable/ServerExecutableService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using System.IO;
using System.Threading.Tasks;
using AsyncAwaitBestPractices.MVVM;
using PropertyChanged.SourceGenerator;
using WDE.Common.Managers;
using WDE.Common.Services.MessageBox;
using WDE.Common.Services.Processes;
using WDE.Module.Attributes;
using WDE.MVVM;

namespace WoWDatabaseEditorCore.Services.ServerExecutable;

[AutoRegister]
[SingleInstance]
public partial class ServerExecutableService : ObservableBase, IServerExecutableService
{
private readonly IProcessService processService;
private readonly IMessageBoxService messageBoxService;
private readonly IServerExecutableConfiguration configuration;
private readonly Lazy<IStatusBar> statusBar;
[Notify] private bool isWorldServerRunning;
[Notify] private bool isAuthServerRunning;
public IAsyncCommand ToggleWorldServer { get; }
public IAsyncCommand ToggleAuthServer { get; }

private IProcess? worldProcess;
private IProcess? authProcess;

public ServerExecutableService(IProcessService processService,
IMessageBoxService messageBoxService,
IServerExecutableConfiguration configuration,
Lazy<IStatusBar> statusBar)
{
this.processService = processService;
this.messageBoxService = messageBoxService;
this.configuration = configuration;
this.statusBar = statusBar;
ToggleWorldServer = new AsyncCommand(async () =>
{
if (string.IsNullOrWhiteSpace(configuration.WorldServerPath) ||
!File.Exists(configuration.WorldServerPath))
{
await ShowConfigureDialog();
return;
}
if (worldProcess != null && worldProcess.IsRunning)
{
worldProcess.Kill();
IsWorldServerRunning = false;
worldProcess = null;
}
else
{
worldProcess = processService.RunAndForget(
configuration.WorldServerPath,
"", Directory.GetParent(configuration.WorldServerPath)?.FullName, true);
worldProcess.OnExit += WorldProcessOnOnExit;
IsWorldServerRunning = true;
}
});

ToggleAuthServer = new AsyncCommand(async () =>
{
if (string.IsNullOrWhiteSpace(configuration.AuthServerPath) ||
!File.Exists(configuration.AuthServerPath))
{
await ShowConfigureDialog();
return;
}
if (authProcess != null && authProcess.IsRunning)
{
authProcess.Kill();
IsAuthServerRunning = false;
authProcess = null;
}
else
{
authProcess = processService.RunAndForget(
configuration.AuthServerPath,
"", Directory.GetParent(configuration.AuthServerPath)?.FullName, true);
authProcess.OnExit += AuthProcessOnOnExit;
IsAuthServerRunning = true;
}
});
}

private Task ShowConfigureDialog()
{
return messageBoxService.ShowDialog(new MessageBoxFactory<bool>()
.SetTitle("Configuration error")
.SetMainInstruction("Setup server path first")
.SetContent("In order to use quick executable start, configure the server paths in the settings")
.WithOkButton(true)
.Build());
}

private void AuthProcessOnOnExit(int code)
{
if (authProcess != null)
authProcess.OnExit -= AuthProcessOnOnExit;
if (code != 0)
statusBar.Value.PublishNotification(new PlainNotification(NotificationType.Warning, "Auth server exited with code " + code));
IsAuthServerRunning = false;
authProcess = null;
}

private void WorldProcessOnOnExit(int code)
{
if (worldProcess != null)
worldProcess.OnExit -= WorldProcessOnOnExit;
if (code != 0)
statusBar.Value.PublishNotification(new PlainNotification(NotificationType.Warning, "World server exited with code " + code));
IsWorldServerRunning = false;
worldProcess = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:serverExecutable="clr-namespace:WoWDatabaseEditorCore.Services.ServerExecutable;assembly=WoWDatabaseEditorCore"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="serverExecutable:ServerExecutableConfigurationPanelViewModel"
x:Class="WoWDatabaseEditorCore.Avalonia.Services.ServerExecutable.ServerExecutableConfigurationPanelView">
<Grid RowDefinitions="Auto,5,Auto" ColumnDefinitions="Auto,5,*,5,Auto">
<TextBlock VerticalAlignment="Center">World server:</TextBlock>
<TextBox Text="{CompiledBinding WorldServerPath}"
Grid.Row="0" Grid.Column="2" />
<Button Grid.Row="0" Grid.Column="4" Command="{CompiledBinding PickWorldPath}" Content="..." />

<TextBlock VerticalAlignment="Center" Grid.Row="2">Auth server:</TextBlock>
<TextBox Text="{CompiledBinding AuthServerPath}"
Grid.Row="2" Grid.Column="2" />
<Button Grid.Row="2" Grid.Column="4" Command="{CompiledBinding PickAuthPath}" Content="..." />
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace WoWDatabaseEditorCore.Avalonia.Services.ServerExecutable;

public class ServerExecutableConfigurationPanelView : UserControl
{
public ServerExecutableConfigurationPanelView()
{
InitializeComponent();
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
Loading

0 comments on commit 55bb290

Please sign in to comment.