diff --git a/Saradomin.sln.DotSettings.user b/Saradomin.sln.DotSettings.user
index f99c7a4..61a8768 100644
--- a/Saradomin.sln.DotSettings.user
+++ b/Saradomin.sln.DotSettings.user
@@ -2,7 +2,4 @@
/usr/share/dotnet/sdk/7.0.100/MSBuild.dll
No
- <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from FindMostRecentBackupDirectory.cs" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
- <Project Location="\home\xacket\Projects\Saradomin-Launcher\UnitTests" Presentation="<UnitTests>" />
-</SessionState>
\ No newline at end of file
diff --git a/Saradomin/Infrastructure/Messaging/ClientClosedMessage.cs b/Saradomin/Infrastructure/Messaging/ClientClosedMessage.cs
new file mode 100644
index 0000000..cf2a276
--- /dev/null
+++ b/Saradomin/Infrastructure/Messaging/ClientClosedMessage.cs
@@ -0,0 +1,8 @@
+using Glitonea.Mvvm.Messaging;
+
+namespace Saradomin.Infrastructure.Messaging;
+
+public class ClientClosedMessage : Message
+{
+
+}
\ No newline at end of file
diff --git a/Saradomin/Infrastructure/Messaging/ClientLaunchRequestedMessage.cs b/Saradomin/Infrastructure/Messaging/ClientLaunchRequestedMessage.cs
new file mode 100644
index 0000000..328c1ef
--- /dev/null
+++ b/Saradomin/Infrastructure/Messaging/ClientLaunchRequestedMessage.cs
@@ -0,0 +1,8 @@
+using Glitonea.Mvvm.Messaging;
+
+namespace Saradomin.Infrastructure.Messaging;
+
+public class ClientLaunchRequestedMessage : Message
+{
+
+}
\ No newline at end of file
diff --git a/Saradomin/Utilities/CrossPlatform.cs b/Saradomin/Utilities/CrossPlatform.cs
index bb452d3..9fc2f19 100644
--- a/Saradomin/Utilities/CrossPlatform.cs
+++ b/Saradomin/Utilities/CrossPlatform.cs
@@ -355,5 +355,41 @@ namespace Saradomin.Utilities
return false;
}
}
+
+ public static Process StartJavaProcess(string javaExecutable, string jarPath, string memoryAllocation, Action outputHandler, Action onExit)
+ {
+ Process process = new Process();
+ process.StartInfo = new ProcessStartInfo
+ {
+ FileName = javaExecutable,
+ Arguments = $"-Xmx{memoryAllocation} -Xms{memoryAllocation} -jar \"{jarPath}\"",
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ WorkingDirectory = Path.Combine(CrossPlatform.GetSingleplayerHome(), "game")
+ };
+
+ process.OutputDataReceived += (_, args) =>
+ {
+ if (string.IsNullOrEmpty(args.Data)) return;
+ outputHandler?.Invoke(args.Data);
+ };
+
+ process.ErrorDataReceived += (_, args) =>
+ {
+ if (string.IsNullOrEmpty(args.Data)) return;
+ outputHandler?.Invoke(args.Data);
+ };
+
+ process.EnableRaisingEvents = true;
+ process.Exited += (_, _) => onExit?.Invoke();
+
+ process.Start();
+
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+ return process;
+ }
}
}
\ No newline at end of file
diff --git a/Saradomin/Utilities/Singleplayer/Windows.cs b/Saradomin/Utilities/Singleplayer/Windows.cs
deleted file mode 100644
index ee4d0f0..0000000
--- a/Saradomin/Utilities/Singleplayer/Windows.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Net.NetworkInformation;
-using System.Threading;
-
-namespace Saradomin.Utilities.Singleplayer;
-
-public static class Windows
-{
- private static bool IsPortInUse(int port)
- {
- var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
- var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
-
- return tcpConnInfoArray.Any(endpoint => endpoint.Port == port);
- }
-
- private static Process StartJavaProcess(string javaExecutable, string jarPath, string memoryAllocation, Action outputHandler, Action onExit)
- {
- Process process = new Process();
- process.StartInfo = new ProcessStartInfo
- {
- FileName = javaExecutable,
- Arguments = $"-Xmx{memoryAllocation} -Xms{memoryAllocation} -jar \"{jarPath}\"",
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- WorkingDirectory = Path.Combine(CrossPlatform.GetSingleplayerHome(), "game")
- };
-
- process.OutputDataReceived += (_, args) =>
- {
- if (string.IsNullOrEmpty(args.Data)) return;
- outputHandler?.Invoke(args.Data);
- };
-
- process.ErrorDataReceived += (_, args) =>
- {
- if (string.IsNullOrEmpty(args.Data)) return;
- outputHandler?.Invoke(args.Data);
- };
-
- process.EnableRaisingEvents = true;
- process.Exited += (_, _) => onExit?.Invoke();
-
- process.Start();
-
- process.BeginOutputReadLine();
- process.BeginErrorReadLine();
- return process;
- }
-
- public static void WindowsLaunchServerAndClient(string javaExecutableLocation, Action log)
- {
- string serverJar = CrossPlatform.GetSingleplayerHome() + @"\game\server.jar";
- string clientJar = CrossPlatform.GetSingleplayerHome() + @"\game\client.jar";
-
- if (IsPortInUse(43595))
- {
- log("Port 43595 is in use. Cannot start the server again.");
- return;
- }
-
- Process serverProcess = StartJavaProcess(javaExecutableLocation, serverJar, "2G", log, null);
-
- while (!IsPortInUse(43595)) Thread.Sleep(1000);
-
- StartJavaProcess(javaExecutableLocation, clientJar, "1G", null, () =>
- {
- serverProcess.Kill();
- });
- }
-
-}
\ No newline at end of file
diff --git a/Saradomin/ViewModel/Controls/SingleplayerViewModel.cs b/Saradomin/ViewModel/Controls/SingleplayerViewModel.cs
index 0c63675..4296959 100644
--- a/Saradomin/ViewModel/Controls/SingleplayerViewModel.cs
+++ b/Saradomin/ViewModel/Controls/SingleplayerViewModel.cs
@@ -14,6 +14,8 @@ using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Threading;
using Glitonea.Mvvm;
+using Glitonea.Mvvm.Messaging;
+using Saradomin.Infrastructure.Messaging;
using Saradomin.Infrastructure.Services;
using Saradomin.Model.Settings.Launcher;
using Saradomin.Utilities;
@@ -35,6 +37,9 @@ public class SingleplayerViewModel : ViewModelBase
public bool ShowLogPanel { get; private set; }
public LauncherSettings Launcher => _settingsService.Launcher;
+ private string _oldServerAddress, _oldManagementAddress;
+ private Process _serverProcess;
+
public SingleplayerViewModel(ISettingsService settingsService,
IJavaUpdateService javaUpdateService,
ISingleplayerUpdateService iSingleplayerUpdateService)
@@ -55,6 +60,18 @@ public class SingleplayerViewModel : ViewModelBase
AcceptsReturn = true,
TextWrapping = TextWrapping.Wrap,
};
+
+ Message.Subscribe(this, OnClientClosed);
+ }
+
+ private void OnClientClosed(ClientClosedMessage _)
+ {
+ if (_serverProcess == null) return;
+ _serverProcess.Kill();
+ _serverProcess = null;
+ CanLaunch = true;
+ _settingsService.Client.GameServerAddress = _oldServerAddress;
+ _settingsService.Client.ManagementServerAddress = _oldManagementAddress;
}
private void OnSingleplayerDownloadProgressChanged(object sender, Tuple e)
@@ -133,21 +150,36 @@ public class SingleplayerViewModel : ViewModelBase
}
CanLaunch = false;
PrintLog("Starting Singleplayer.. The Singleplayer client will launch when 2009scape is ready. Sit tight!");
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- new Task(() => Utilities.Singleplayer.Windows.WindowsLaunchServerAndClient(Launcher.JavaExecutableLocation, PrintLog)).Start();
- }
- else
- {
- new Task(() =>
- CrossPlatform.RunCommandAndGetOutput(
- $"{CrossPlatform.LocateSingleplayerExecutable()} \"{Launcher.JavaExecutableLocation}\"",
- PrintLog,
- PrintLog)
- ).Start();
- }
+
+ _oldServerAddress = _settingsService.Client.GameServerAddress;
+ _oldManagementAddress = _settingsService.Client.ManagementServerAddress;
+ _settingsService.Client.GameServerAddress = _settingsService.Client.ManagementServerAddress = "localhost";
+ new Task(() => LaunchServerAndClient(Launcher.JavaExecutableLocation, PrintLog)).Start();
}
+ private void LaunchServerAndClient (string javaExecutableLocation, Action log)
+ {
+ var serverJar = CrossPlatform.GetSingleplayerHome() + @"/game/server.jar";
+
+ if (IsPortInUse(43595))
+ {
+ log("Port 43595 is in use. Cannot start the server again.");
+ return;
+ }
+
+ _serverProcess = CrossPlatform.StartJavaProcess(javaExecutableLocation, serverJar, "2G", log, null);
+ while (!IsPortInUse(43595)) Thread.Sleep(1000);
+ Message.Broadcast();
+ }
+
+ private static bool IsPortInUse(int port)
+ {
+ var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
+ var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
+
+ return tcpConnInfoArray.Any(endpoint => endpoint.Port == port);
+ }
+
private void LaunchFaq()
{
CrossPlatform.LaunchURL("https://2009scape.org/site/game_guide/singleplayer.html");
diff --git a/Saradomin/ViewModel/Windows/MainWindowViewModel.cs b/Saradomin/ViewModel/Windows/MainWindowViewModel.cs
index 4098672..49bdf08 100644
--- a/Saradomin/ViewModel/Windows/MainWindowViewModel.cs
+++ b/Saradomin/ViewModel/Windows/MainWindowViewModel.cs
@@ -58,6 +58,7 @@ namespace Saradomin.ViewModel.Windows
Message.Subscribe(this, MainViewLoaded);
Message.Subscribe(this, NotificatationBoxStateChanged);
+ Message.Subscribe(this, ClientLaunchRequested);
_settingsService.Launcher.JavaExecutableLocation ??= CrossPlatform.LocateJavaExecutable();
}
@@ -67,6 +68,12 @@ namespace Saradomin.ViewModel.Windows
Environment.Exit(0);
}
+ public async void ClientLaunchRequested(ClientLaunchRequestedMessage _)
+ {
+ if (CanLaunch)
+ await ExecuteLaunchSequence();
+ }
+
public async void MainViewLoaded(MainViewLoadedMessage _)
{
using (var httpClient = new HttpClient())
@@ -117,7 +124,13 @@ namespace Saradomin.ViewModel.Windows
public bool CanExecuteLaunchSequence(object param)
=> CanLaunch;
+ //Stub to maintain compatibility with AXAML
public async Task ExecuteLaunchSequence()
+ {
+ await ExecuteLaunchSequence(false);
+ }
+
+ private async Task ExecuteLaunchSequence(bool forceWait)
{
CanLaunch = false;
@@ -159,7 +172,7 @@ namespace Saradomin.ViewModel.Windows
// Will block this task until client process exits.
var t = _launchService.LaunchClient();
- if (!_settingsService.Launcher.AllowMultiboxing)
+ if (!_settingsService.Launcher.AllowMultiboxing || forceWait)
await t;
}
}
@@ -174,6 +187,7 @@ namespace Saradomin.ViewModel.Windows
{
CanLaunch = true;
LaunchText = "Play!";
+ Message.Broadcast();
}
}