diff --git a/Saradomin.sln.DotSettings b/Saradomin.sln.DotSettings
index ff21452..0044dd2 100644
--- a/Saradomin.sln.DotSettings
+++ b/Saradomin.sln.DotSettings
@@ -1,2 +1,3 @@
+ True
True
\ No newline at end of file
diff --git a/Saradomin.sln.DotSettings.user b/Saradomin.sln.DotSettings.user
index d39f247..f99c7a4 100644
--- a/Saradomin.sln.DotSettings.user
+++ b/Saradomin.sln.DotSettings.user
@@ -2,7 +2,7 @@
/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 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/Services/SettingsService.cs b/Saradomin/Infrastructure/Services/SettingsService.cs
index 5bd999f..9e3f71e 100644
--- a/Saradomin/Infrastructure/Services/SettingsService.cs
+++ b/Saradomin/Infrastructure/Services/SettingsService.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
using System.Text.Json;
using Saradomin.Model.Settings.Client;
diff --git a/Saradomin/Utilities/SingleplayerManagement.cs b/Saradomin/Utilities/Singleplayer/SingleplayerManagement.cs
similarity index 96%
rename from Saradomin/Utilities/SingleplayerManagement.cs
rename to Saradomin/Utilities/Singleplayer/SingleplayerManagement.cs
index d40c9d5..a4fe832 100644
--- a/Saradomin/Utilities/SingleplayerManagement.cs
+++ b/Saradomin/Utilities/Singleplayer/SingleplayerManagement.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net.NetworkInformation;
namespace Saradomin.Utilities;
@@ -22,15 +23,11 @@ public static class SingleplayerManagement
public static void MakeBackup(Action log)
{
- if (!Directory.Exists(CrossPlatform.GetSingleplayerBackupsHome()))
- Directory.CreateDirectory(CrossPlatform.GetSingleplayerBackupsHome());
-
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string newBackupDir = Path.Combine(
CrossPlatform.GetSingleplayerBackupsHome(),
timestamp
);
- Directory.CreateDirectory(newBackupDir);
foreach (string dir in DirsToBackup)
{
diff --git a/Saradomin/Utilities/Singleplayer/Windows.cs b/Saradomin/Utilities/Singleplayer/Windows.cs
new file mode 100644
index 0000000..ee4d0f0
--- /dev/null
+++ b/Saradomin/Utilities/Singleplayer/Windows.cs
@@ -0,0 +1,77 @@
+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 aa07d1e..d783b3d 100644
--- a/Saradomin/ViewModel/Controls/SingleplayerViewModel.cs
+++ b/Saradomin/ViewModel/Controls/SingleplayerViewModel.cs
@@ -1,8 +1,13 @@
using System;
+using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
+using System.Linq;
using System.Net.Http;
+using System.Net.NetworkInformation;
+using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
+using System.Threading;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
@@ -73,7 +78,7 @@ public class SingleplayerViewModel : ViewModelBase
public void DownloadSingleplayer()
{
- if (!CanLaunch) return; // While the button could be disabled, this looks nicer visually (since we update the download progress in the button text)
+ if (File.Exists(CrossPlatform.LocateSingleplayerExecutable()) && !CanLaunch) return; // While the button could be disabled, this looks nicer visually (since we update the download progress in the button text)
CanLaunch = false;
MakeBackup();
PrintLog($"Starting singleplayer download...");
@@ -103,6 +108,8 @@ public class SingleplayerViewModel : ViewModelBase
private void PrintLog(string message)
{
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) message = Regex.Replace(message, @"\e\[[0-9;]*m", string.Empty);
+
ShowLogPanel = true;
Dispatcher.UIThread.Post(() => { SingleplayerLogsTextBox.Text += message + Environment.NewLine; },
DispatcherPriority.Background);
@@ -113,12 +120,19 @@ public class SingleplayerViewModel : ViewModelBase
public void LaunchSingleplayer()
{
CanLaunch = false;
- new Task(() =>
- CrossPlatform.RunCommandAndGetOutput(
- $"{CrossPlatform.LocateSingleplayerExecutable()} {Launcher.JavaExecutableLocation}",
- PrintLog,
- PrintLog)
- ).Start();
+ 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();
+ }
}
private void LaunchFaq()
diff --git a/Saradomin/ViewModel/Windows/MainWindowViewModel.cs b/Saradomin/ViewModel/Windows/MainWindowViewModel.cs
index b31c06f..a9247ae 100644
--- a/Saradomin/ViewModel/Windows/MainWindowViewModel.cs
+++ b/Saradomin/ViewModel/Windows/MainWindowViewModel.cs
@@ -25,9 +25,6 @@ namespace Saradomin.ViewModel.Windows
private readonly IRemoteConfigService _remoteConfigService;
private readonly ISettingsService _settingsService;
- private bool JavaExecutableValid
- => CrossPlatform.IsJavaExecutableValid(_settingsService.Launcher.JavaExecutableLocation);
-
private LauncherSettings Launcher { get; }
public string Title { get; set; } = "2009scape launcher";
@@ -50,9 +47,7 @@ namespace Saradomin.ViewModel.Windows
_remoteConfigService = remoteConfigService;
_javaUpdateService = javaUpdateService;
_javaUpdateService.JavaDownloadProgressChanged += OnJavaDownloadProgressUpdated;
-
-
_settingsService = settingsService;
Launcher = _settingsService.Launcher;
@@ -62,13 +57,9 @@ namespace Saradomin.ViewModel.Windows
};
Message.Subscribe(this, MainViewLoaded);
- Message.Subscribe(this, SettingsModified);
Message.Subscribe(this, NotificatationBoxStateChanged);
- if (!JavaExecutableValid)
- {
- _settingsService.Launcher.JavaExecutableLocation = CrossPlatform.LocateJavaExecutable();
- }
+ _settingsService.Launcher.JavaExecutableLocation ??= CrossPlatform.LocateJavaExecutable();
}
public void ExitApplication()
@@ -102,23 +93,6 @@ namespace Saradomin.ViewModel.Windows
}
}
- public void SettingsModified(SettingsModifiedMessage msg)
- {
- if (msg.SettingName == nameof(LauncherSettings.JavaExecutableLocation))
- {
- if (!JavaExecutableValid)
- {
- CanLaunch = false;
- LaunchText = "Unable to locate Java. Find Java executable using Settings page.";
- }
- else
- {
- CanLaunch = true;
- LaunchText = "Play!";
- }
- }
- }
-
public void NotificatationBoxStateChanged(NotificationBoxStateChangedMessage msg)
{
DimContent = msg.WasOpened;