From 90b8027be1f93ee6530396fd68ca0d92a918f8e1 Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 27 Mar 2024 23:36:09 -0500 Subject: [PATCH] Make singleplayer actually use the launcher's client and configuration. --- Saradomin.sln.DotSettings.user | 3 - .../Messaging/ClientClosedMessage.cs | 8 ++ .../Messaging/ClientLaunchRequestedMessage.cs | 8 ++ Saradomin/Utilities/CrossPlatform.cs | 36 +++++++++ Saradomin/Utilities/Singleplayer/Windows.cs | 77 ------------------- .../Controls/SingleplayerViewModel.cs | 58 ++++++++++---- .../ViewModel/Windows/MainWindowViewModel.cs | 16 +++- 7 files changed, 112 insertions(+), 94 deletions(-) create mode 100644 Saradomin/Infrastructure/Messaging/ClientClosedMessage.cs create mode 100644 Saradomin/Infrastructure/Messaging/ClientLaunchRequestedMessage.cs delete mode 100644 Saradomin/Utilities/Singleplayer/Windows.cs 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="&lt;UnitTests&gt;" /> -</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(); } }