Add Avalonia server-host launcher (MVP scaffold)
Cross-platform C# GUI to replace the Qt/C++ Host GUI, on the same dotnet toolchain as the server. MVP: load/save commonwealth-server.json, Start/Stop the CommonwealthOnline.Server process (published exe, then dll, then source run), and stream its output to a live log. Themed to the Commonwealth Online brand (near-black + amber). Builds clean on net8.0. Next: player list + kick/ban via the admin port, then retire the Qt host.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using Avalonia.Threading;
|
||||
using CommonwealthOnline.Host.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace CommonwealthOnline.Host.ViewModels;
|
||||
|
||||
public partial class MainWindowViewModel : ObservableObject
|
||||
{
|
||||
private const int MaxLogLines = 2000;
|
||||
|
||||
private readonly ServerController _controller = new();
|
||||
private readonly string _serverDir = System.IO.Directory.GetCurrentDirectory();
|
||||
private readonly string _configPath =
|
||||
Path.Combine(System.IO.Directory.GetCurrentDirectory(), "commonwealth-server.json");
|
||||
|
||||
[ObservableProperty] private string _serverName;
|
||||
[ObservableProperty] private string _host;
|
||||
[ObservableProperty] private int _port;
|
||||
[ObservableProperty] private int _maxPlayers;
|
||||
[ObservableProperty] private int _adminPort;
|
||||
[ObservableProperty] private string _logVerbosity;
|
||||
[ObservableProperty] private bool _enableGnsTransport;
|
||||
[ObservableProperty] private bool _isRunning;
|
||||
[ObservableProperty] private string _statusText = "Stopped";
|
||||
|
||||
public ObservableCollection<string> Log { get; } = new();
|
||||
|
||||
public string[] VerbosityOptions { get; } = { "error", "warning", "info", "debug" };
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
var config = ServerConfig.Load(_configPath);
|
||||
_serverName = config.ServerName;
|
||||
_host = config.Host;
|
||||
_port = config.Port;
|
||||
_maxPlayers = config.MaxPlayers;
|
||||
_adminPort = config.AdminPort;
|
||||
_logVerbosity = config.LogVerbosity;
|
||||
_enableGnsTransport = config.EnableGnsTransport;
|
||||
|
||||
_controller.LogReceived += line =>
|
||||
Dispatcher.UIThread.Post(() => Append(line));
|
||||
_controller.RunningChanged += running =>
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsRunning = running;
|
||||
StatusText = running ? "Running" : "Stopped";
|
||||
StartCommand.NotifyCanExecuteChanged();
|
||||
StopCommand.NotifyCanExecuteChanged();
|
||||
});
|
||||
}
|
||||
|
||||
private void Append(string line)
|
||||
{
|
||||
Log.Add(line);
|
||||
while (Log.Count > MaxLogLines)
|
||||
{
|
||||
Log.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
private ServerConfig CurrentConfig() => new()
|
||||
{
|
||||
ServerName = ServerName,
|
||||
Host = Host,
|
||||
Port = Port,
|
||||
MaxPlayers = MaxPlayers,
|
||||
AdminPort = AdminPort,
|
||||
LogVerbosity = LogVerbosity,
|
||||
EnableGnsTransport = EnableGnsTransport,
|
||||
};
|
||||
|
||||
[RelayCommand]
|
||||
private void Save() => CurrentConfig().Save(_configPath);
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanStart))]
|
||||
private void Start()
|
||||
{
|
||||
Save();
|
||||
Append($"[host] starting server on {Host}:{Port}...");
|
||||
_controller.Start(_serverDir, _configPath);
|
||||
}
|
||||
|
||||
private bool CanStart() => !IsRunning;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanStop))]
|
||||
private void Stop()
|
||||
{
|
||||
Append("[host] stopping server...");
|
||||
_controller.Stop();
|
||||
}
|
||||
|
||||
private bool CanStop() => IsRunning;
|
||||
}
|
||||
Reference in New Issue
Block a user