From 96cefe574905f56a51608d51dc693683cd078cc9 Mon Sep 17 00:00:00 2001 From: Max Nullov Date: Fri, 21 Feb 2025 16:09:06 +0300 Subject: [PATCH] Version 1.1.0 | Settings and gitlab repo --- src/Launcher/Launcher.cs | 37 ++++--- src/Launcher/Program.cs | 2 +- src/Launcher/Utils.cs | 2 +- src/LauncherGUI/Assets/cog.png | Bin 0 -> 892 bytes src/LauncherGUI/Assets/gitlab-logo.png | Bin 0 -> 939 bytes src/LauncherGUI/Assets/toml-paper.png | Bin 0 -> 911 bytes src/LauncherGUI/ConfigManager.cs | 75 +++++++++++++++ src/LauncherGUI/LauncherGUI.csproj | 1 + src/LauncherGUI/LauncherUtils.cs | 23 +++++ src/LauncherGUI/Program.cs | 2 +- .../ViewModels/LoadingWindowViewModel.cs | 2 +- .../ViewModels/MainWindowViewModel.cs | 9 +- .../ViewModels/SettingsWindowViewModel.cs | 6 ++ .../VersionSelectorWindowViewModel.cs | 4 +- src/LauncherGUI/ViewModels/ViewModelBase.cs | 1 + src/LauncherGUI/Views/LoadingWindow.axaml | 91 ++++++++++-------- src/LauncherGUI/Views/LoadingWindow.axaml.cs | 27 +++++- src/LauncherGUI/Views/MainWindow.axaml | 66 +++++++++---- src/LauncherGUI/Views/MainWindow.axaml.cs | 59 +++++++++--- src/LauncherGUI/Views/SettingsWindow.axaml | 54 +++++++++++ src/LauncherGUI/Views/SettingsWindow.axaml.cs | 41 ++++++++ .../Views/VersionSelectorWindow.axaml.cs | 12 +-- src/LauncherGUI/tweaks.toml | 4 + 23 files changed, 403 insertions(+), 115 deletions(-) create mode 100644 src/LauncherGUI/Assets/cog.png create mode 100644 src/LauncherGUI/Assets/gitlab-logo.png create mode 100644 src/LauncherGUI/Assets/toml-paper.png create mode 100644 src/LauncherGUI/ConfigManager.cs create mode 100644 src/LauncherGUI/LauncherUtils.cs create mode 100644 src/LauncherGUI/ViewModels/SettingsWindowViewModel.cs create mode 100644 src/LauncherGUI/Views/SettingsWindow.axaml create mode 100644 src/LauncherGUI/Views/SettingsWindow.axaml.cs create mode 100644 src/LauncherGUI/tweaks.toml diff --git a/src/Launcher/Launcher.cs b/src/Launcher/Launcher.cs index 4538625..aeaa9f6 100644 --- a/src/Launcher/Launcher.cs +++ b/src/Launcher/Launcher.cs @@ -1,4 +1,4 @@ -using System.Formats.Tar; +using System.Formats.Tar; using System.Net; using System.Runtime.InteropServices; using System.Security.AccessControl; @@ -6,7 +6,7 @@ using CmlLib.Core; using CmlLib.Core.Auth; using CmlLib.Core.ProcessBuilder; -namespace BlightFlame +namespace PlombirLauncher { /* Basically a class to manage everything launcher related. @@ -22,11 +22,11 @@ namespace BlightFlame public int DownloadProgress; public string DownloadStatus; - public Launcher(string userName, string version) + public Launcher(string userName, string version, string? location = null) { _version = version; _nickname = userName; - _mcPath = new($"./runtime/{version}/minecraft"); + _mcPath = new($"{location}/{version}/minecraft"); _mcLauncher = new(_mcPath); } @@ -43,7 +43,7 @@ namespace BlightFlame // System.Uri download_uri = new("https://dixxe.top/static/distro/cmllibcore-minecraft-forge-1201.tar.xz"); // WebClient client = new(); - + // if ((!File.Exists(archieve)) && (!Directory.Exists(runtimePath))) // { // DownloadStatus = "Fetching deploy-minecraft from host..."; @@ -72,7 +72,7 @@ namespace BlightFlame // // Waiting for archieve to download. // await tcs.Task; // } - + // DownloadStatus = "Unarchiving modpack..."; // unarchiveMinecraft(archieve, runtimePath); @@ -86,7 +86,7 @@ namespace BlightFlame // Directory.CreateDirectory(path); // Utils.UnzipTarGzFile(archieveName, path); - // if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + // if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) // { // Utils.LinuxExec($"chmod -R +x {path}/"); // Console.WriteLine("Execute permissions added successfully."); @@ -94,47 +94,46 @@ namespace BlightFlame // File.Delete(archieveName); // } - - async public Task BuildLauncher() + + async public Task BuildLauncher(CancellationToken token) { - - _mcLauncher.ByteProgressChanged += (_, args) => { Console.WriteLine($"{(int)(args.ProgressedBytes * 0.000001)} MBytes / {(int)(args.TotalBytes * 0.000001)} MBytes"); DownloadProgress = (int)(args.ProgressedBytes * 100 / args.TotalBytes); }; - + // Before installAsync I should fetch lightweight minecraft instance from webserver // Then installAsync will download any runtime needed stuff. // This method is FetchMinecraft() // Currently this is only one viable option for forge installations. // But it requires server, so forge (and all mod loaders) is disabled. //await FetchMinecraft(); - + DownloadStatus = "Installing minecraft..."; Console.WriteLine(DownloadStatus); await _mcLauncher.InstallAsync(_version); DownloadStatus = "Finished!"; Console.WriteLine(DownloadStatus); + return; } - async public Task RunLauncher() + async public Task RunLauncher() { - var process = await _mcLauncher.BuildProcessAsync(_version, new MLaunchOption{ - + var process = await _mcLauncher.BuildProcessAsync(_version, new MLaunchOption + { + Session = MSession.CreateOfflineSession(_nickname), MaximumRamMb = 4096, }) ?? throw new Exception("Failed to start minecraft process!"); - + var processUtil = new ProcessWrapper(process); processUtil.OutputReceived += (s, e) => Console.WriteLine(e); processUtil.StartWithEvents(); - + await processUtil.WaitForExitTaskAsync(); } } } - diff --git a/src/Launcher/Program.cs b/src/Launcher/Program.cs index a304e9e..052e051 100644 --- a/src/Launcher/Program.cs +++ b/src/Launcher/Program.cs @@ -1,4 +1,4 @@ -namespace BlightFlame +namespace PlombirLauncher { sealed class Program { diff --git a/src/Launcher/Utils.cs b/src/Launcher/Utils.cs index 82c084b..86fe32c 100644 --- a/src/Launcher/Utils.cs +++ b/src/Launcher/Utils.cs @@ -7,7 +7,7 @@ using SharpCompress.Readers; using System.Diagnostics; using CmlLib.Core; -namespace BlightFlame +namespace PlombirLauncher { static public class Utils { diff --git a/src/LauncherGUI/Assets/cog.png b/src/LauncherGUI/Assets/cog.png new file mode 100644 index 0000000000000000000000000000000000000000..3e448f34ab0b74adfd3e49aa9fdf36021349954f GIT binary patch literal 892 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuFE&V0QL&aSW-L^Y(6R-c zX5+5t4bRK>By8olS@h!F3DM+Tr+7TP7(6)@G#OP)S8?oI)ccaPx~ok)=HtHQ+uLR` zLS$4Mmb|;rS6U){`OBlEtMi<4e6nXqLQMu*%IA7wp3@^u*5j)d-~aw)u8}dwG@u@q z30GE>tzn3Pecklb3`gpN_ z(dYMkzAKalwTe?=WvuIo4Xp1jtvj@#`Q2)_`-}EjEsJ)Ygye;uxf2Y#zl)c#t(vyp zF!^iK_VWB~GZ4Q2CZ<>(<1&9;R=3nPk&li48t0|xG`=oXuwZlAPeY6Tz95L?S{ zt$3#q78^ZfYu;a*_vL8wzCWeE-kUN*A_?ew-`_6pm$?31(v)#&_fHr7^NP@zn)R*o z-sRhq<1E$(Zk@Ha*1NJ|_n+Hm5YagKoIuKM<;i;gZWkSY9-WGCMOBsHrl(!4|8KX& zF006ReN_x84z>W}zQB1-zu4_uVOhoFw_o5QQtDaD5o!B>W4hv>DM?RX7<%L-m?I3k z`|x#y_qQ!9a|^C1?<^@SbP0l+XkKUgLia literal 0 HcmV?d00001 diff --git a/src/LauncherGUI/Assets/gitlab-logo.png b/src/LauncherGUI/Assets/gitlab-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f28b856e001f5d88a74cd3d5628a789d80de1a41 GIT binary patch literal 939 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuFE&U@r1>aSW-L^Y*TGpGcqt>w{;a zFM1eRI7E6JA4D+lH79VY=rp!&U=f7WeW*^dF znV`X_;>FNuWq-JOn_gOUeOXB0qAO>OjTk$H92S9Pv-*ULcE7q@yIXnrt*a4H0PYbg58-}64&aOT4qp)E)f$=)7Wjk^mCZx+Vd_je&lc;Dd6y!uuB-xVLI z;Xtcl_CT0rnd&VQyxG(Lmg-FNgi5XmR9zBPBUk_bal{oq>ph$0Vt)U5dHvY?bS9`n zm^`km5ZYuX@$CDtv)#?v@9)d??&MVreQ5FPUv+@Z`ncU2KH4JLC>83o>S+2_58FMP z^KQuoh83+k6c{N#M>=Nr-zP_peK$q&`=|eI|K7bk{OZ#&_bnomUv3ra6Xr2m+_E8p z2^tKg|BrsjI=E)W6}M^K9Kz7h1bS&3&<@$@z2)vv;w5RCUOcl_Tidt) zkBrUoeEB+_xa-xZs*P2be0utI@wMsSLVRY;J2|!b{PTad+YTWG(Of;nspq;*#)gTe~DWM4fz{7-G literal 0 HcmV?d00001 diff --git a/src/LauncherGUI/Assets/toml-paper.png b/src/LauncherGUI/Assets/toml-paper.png new file mode 100644 index 0000000000000000000000000000000000000000..bff43123749e8fb3e19648f12cc1639552b9689d GIT binary patch literal 911 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuFE&U=H(iaSW-L^Y*S|pK!QH>qE9y z#*Pgf%Q!kEXD3YC(66J)?fGp|HZh|A*Pps?o>O{T_3Oo{{c(3c z9cBia$G~tP(srf(gKPWhe&wE?|9|uK(l-xY{lB|8{Qb8*eZKRqi65vHb_inf@M7?s zyR2o-ikLUKFE=GIO%j3$?rqTt)~oyTaC!Iqzn@;8KRDGUON+Z&Tv&L*6b6W@R})m9 zNc-7N(^ORM>g4qBVesTs&}398T_&`t_e55 zm%;tYbsz4}o-DxU4b`%=C8s3+XiA91y!{n*6Bl34xA)mQ4`J)nsS}jn)t|BQHk1_Y zbB}rQ;_UDK;Q9Yy zGpqLAJYV6q5 zb~0Q`Mi~)3Q-q2b`fcpKzk2^H0vMmLa4&sz^vl)xF|9~3JWHr(+M$i#%PZELL&Tny zFQ=rXw;?EwkZfC}qqw+s%1YabKp&kJ`gKCk`>dA_G>vg8tSmCD{TBW{tMTs{?-xi; z2?=v@6Pa9W-&cMFVL{ZYmYy1CLrF{5NXygW!hJJ9X$q1UPfwo^`Ms>GXxi;<2*bhI dfZ>n+Kh~`M|8_3V555f&@pScbS?83{1ONg&a4Y}- literal 0 HcmV?d00001 diff --git a/src/LauncherGUI/ConfigManager.cs b/src/LauncherGUI/ConfigManager.cs new file mode 100644 index 0000000..2d6124e --- /dev/null +++ b/src/LauncherGUI/ConfigManager.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using Tommy; + +namespace PlombirLauncher; + +public class ConfigManager +{ + public static void BuildDefault() + { + TomlTable toml = new TomlTable + { + ["title"] = "Launcher tweaks file!", + + ["runtime-path"] = new TomlString + { + Value = "./runtime", + Comment = "Path to folder that will hold all minecraft versions" + }, + + ["last-version-launched"] = new TomlString + { + Value = "1.20.1", + Comment = "Saving last launched version to use it after launch" + }, + + ["nickname"] = "slugcat" + }; + + using(StreamWriter writer = File.CreateText("tweaks.toml")) + { + toml.WriteTo(writer); + // Remember to flush the data if needed! + writer.Flush(); + } + } + + public static dynamic? ReadConfig(string key) + { + if (!File.Exists("tweaks.toml")) + { + BuildDefault(); + } + using(StreamReader reader = File.OpenText("tweaks.toml")) + { + TomlTable table = TOML.Parse(reader); + + return table[key]; + } + } + + public static void WriteInConfig(string key, dynamic value) + { + if (!File.Exists("tweaks.toml")) + { + BuildDefault(); + } + + TomlTable table; + + using(StreamReader reader = File.OpenText("tweaks.toml")) + { + table = TOML.Parse(reader); + + table[key] = value; + } + + using(StreamWriter writer = File.CreateText("tweaks.toml")) + { + table.WriteTo(writer); + // Remember to flush the data if needed! + writer.Flush(); + } + } +} \ No newline at end of file diff --git a/src/LauncherGUI/LauncherGUI.csproj b/src/LauncherGUI/LauncherGUI.csproj index 2b9cc47..ffb860d 100644 --- a/src/LauncherGUI/LauncherGUI.csproj +++ b/src/LauncherGUI/LauncherGUI.csproj @@ -28,6 +28,7 @@ All + diff --git a/src/LauncherGUI/LauncherUtils.cs b/src/LauncherGUI/LauncherUtils.cs new file mode 100644 index 0000000..4d66092 --- /dev/null +++ b/src/LauncherGUI/LauncherUtils.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Avalonia.Controls; +using LauncherGUI.ViewModels; +using LauncherGUI.Views; + +namespace PlombirLauncher; + +public class LauncherUtils +{ + public async static Task CreateMinecraftInstance(MainWindowViewModel vm, Window windowCaller) + { + System.Console.WriteLine($"Creating minecraft instance for {vm.Usernick}, {vm.SelectedVersion} in {vm.RuntimeLocation}"); + LoadingWindow loading = new(vm.Usernick, vm.SelectedVersion, vm.RuntimeLocation); + ConfigManager.WriteInConfig("last-version-launched", vm.SelectedVersion); + ConfigManager.WriteInConfig("nickname", vm.Usernick); + + loading.Show(); + await loading.InitLoading(); + loading.Close(); + await loading.RunMinecraft(); + return; + } +} \ No newline at end of file diff --git a/src/LauncherGUI/Program.cs b/src/LauncherGUI/Program.cs index 116a17d..860be03 100644 --- a/src/LauncherGUI/Program.cs +++ b/src/LauncherGUI/Program.cs @@ -1,5 +1,5 @@ using Avalonia; -using BlightFlame; +using PlombirLauncher; using System; namespace LauncherGUI; diff --git a/src/LauncherGUI/ViewModels/LoadingWindowViewModel.cs b/src/LauncherGUI/ViewModels/LoadingWindowViewModel.cs index e6821b1..084f6df 100644 --- a/src/LauncherGUI/ViewModels/LoadingWindowViewModel.cs +++ b/src/LauncherGUI/ViewModels/LoadingWindowViewModel.cs @@ -2,7 +2,7 @@ namespace LauncherGUI.ViewModels; public partial class LoadingWindowViewModel : ViewModelBase { - private long _loadingProgress; + private long _loadingProgress = 0; public long Progress {get => _loadingProgress; set {_loadingProgress = value; OnPropertyChanged(nameof(Progress)); }} private string _loadingStatus = "Rotating transistors.."; diff --git a/src/LauncherGUI/ViewModels/MainWindowViewModel.cs b/src/LauncherGUI/ViewModels/MainWindowViewModel.cs index 6d46bca..387e1d8 100644 --- a/src/LauncherGUI/ViewModels/MainWindowViewModel.cs +++ b/src/LauncherGUI/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using BlightFlame; +using PlombirLauncher; namespace LauncherGUI.ViewModels; @@ -7,9 +7,12 @@ public partial class MainWindowViewModel : ViewModelBase { public string Greeting { get; } = "Plombir launcher"; - private string _userNick = "slugcat"; + private string _userNick = ConfigManager.ReadConfig("nickname"); public string Usernick {get => _userNick; set {_userNick = value; OnPropertyChanged(nameof(Usernick)); }} - private string _selectedVersion = "1.20.1"; + private string _selectedVersion = ConfigManager.ReadConfig("last-version-launched"); public string SelectedVersion {get => _selectedVersion; set {_selectedVersion = value; OnPropertyChanged(nameof(SelectedVersion)); }} + + private string _runtimeLocation = ConfigManager.ReadConfig("runtime-path"); + public string RuntimeLocation {get => _runtimeLocation; set {_runtimeLocation = value; OnPropertyChanged(nameof(RuntimeLocation)); }} } diff --git a/src/LauncherGUI/ViewModels/SettingsWindowViewModel.cs b/src/LauncherGUI/ViewModels/SettingsWindowViewModel.cs new file mode 100644 index 0000000..3848b0f --- /dev/null +++ b/src/LauncherGUI/ViewModels/SettingsWindowViewModel.cs @@ -0,0 +1,6 @@ +namespace LauncherGUI.ViewModels; + +public partial class SettingsWindowViewModel : ViewModelBase +{ + // I save launcher data mostly in MainWindowViewModel. +} diff --git a/src/LauncherGUI/ViewModels/VersionSelectorWindowViewModel.cs b/src/LauncherGUI/ViewModels/VersionSelectorWindowViewModel.cs index c5dba50..f9c2fdf 100644 --- a/src/LauncherGUI/ViewModels/VersionSelectorWindowViewModel.cs +++ b/src/LauncherGUI/ViewModels/VersionSelectorWindowViewModel.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; -using BlightFlame; +using PlombirLauncher; using LauncherGUI.ViewModels; namespace LauncherGUI.ViewModels; public partial class VersionSelectorWindowViewModel : ViewModelBase { - + // I save launcher data mostly in MainWindowViewModel. } \ No newline at end of file diff --git a/src/LauncherGUI/ViewModels/ViewModelBase.cs b/src/LauncherGUI/ViewModels/ViewModelBase.cs index 0b1a0a9..3773f09 100644 --- a/src/LauncherGUI/ViewModels/ViewModelBase.cs +++ b/src/LauncherGUI/ViewModels/ViewModelBase.cs @@ -4,4 +4,5 @@ namespace LauncherGUI.ViewModels; public class ViewModelBase : ObservableObject { + // I save launcher data mostly in MainWindowViewModel. } diff --git a/src/LauncherGUI/Views/LoadingWindow.axaml b/src/LauncherGUI/Views/LoadingWindow.axaml index 1b11eaf..4c287ab 100644 --- a/src/LauncherGUI/Views/LoadingWindow.axaml +++ b/src/LauncherGUI/Views/LoadingWindow.axaml @@ -1,58 +1,65 @@ - - - - - - + - - - + + + - + + - + + + + + + - - + + - - + + - - - \ No newline at end of file + + + diff --git a/src/LauncherGUI/Views/LoadingWindow.axaml.cs b/src/LauncherGUI/Views/LoadingWindow.axaml.cs index ae923b7..879574c 100644 --- a/src/LauncherGUI/Views/LoadingWindow.axaml.cs +++ b/src/LauncherGUI/Views/LoadingWindow.axaml.cs @@ -3,17 +3,22 @@ using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.VisualTree; -using BlightFlame; +using PlombirLauncher; using LauncherGUI.ViewModels; +using System.Threading; namespace LauncherGUI.Views; public partial class LoadingWindow : Window { private Launcher ln; - public LoadingWindow(string nickname, string? version = null) + private Task _buildingTask; + + // Tokens for controlling download task. + CancellationTokenSource tokenSource = new CancellationTokenSource(); + public LoadingWindow(string nickname, string? version = null, string? location = null) { - ln = new Launcher(nickname, version ?? "1.20.1"); + ln = new Launcher(nickname, version ?? "1.20.1", location ?? "./runtime"); InitializeComponent(); DataContext = new LoadingWindowViewModel(); } @@ -25,6 +30,7 @@ public partial class LoadingWindow : Window { throw new InvalidOperationException("No DataContext set"); } + Task updateGui = new Task(async () => { while (ln.DownloadStatus != "Finished!"){ viewModel.Progress = ln.DownloadProgress; @@ -33,16 +39,27 @@ public partial class LoadingWindow : Window } viewModel.Progress = 100; }); + updateGui.Start(); - await ln.BuildLauncher(); + + _buildingTask = ln.BuildLauncher(tokenSource.Token); + await _buildingTask; + - } public async Task RunMinecraft() { await ln.RunLauncher(); } + + private void onStopDownloadClick(object sender, RoutedEventArgs e) + { + var button = sender as Button; + tokenSource.Cancel(); + System.Console.WriteLine("Loading disabled gracefully."); + Close(); + } } \ No newline at end of file diff --git a/src/LauncherGUI/Views/MainWindow.axaml b/src/LauncherGUI/Views/MainWindow.axaml index 503a0e2..20ea829 100644 --- a/src/LauncherGUI/Views/MainWindow.axaml +++ b/src/LauncherGUI/Views/MainWindow.axaml @@ -48,8 +48,25 @@ + HorizontalAlignment="Right" Text="v1.1.0 - nullmax17"/> + + + + + + + + + @@ -98,26 +115,35 @@ HorizontalAlignment="Center"/> + + + + + + + + + + + - - - - - - - - - - - - + + + + + + diff --git a/src/LauncherGUI/Views/MainWindow.axaml.cs b/src/LauncherGUI/Views/MainWindow.axaml.cs index ef4ec39..5dc7429 100644 --- a/src/LauncherGUI/Views/MainWindow.axaml.cs +++ b/src/LauncherGUI/Views/MainWindow.axaml.cs @@ -4,9 +4,11 @@ using System.Linq; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.VisualTree; -using BlightFlame; +using PlombirLauncher; using CmlLib.Core.VersionMetadata; using LauncherGUI.ViewModels; +using System.Diagnostics; +using System.Runtime.InteropServices; namespace LauncherGUI.Views; @@ -17,7 +19,7 @@ public partial class MainWindow : Window { InitializeComponent(); DataContext = new MainWindowViewModel(); - if (DataContext == null) throw new NullReferenceException("Cant load MainWindow DataContext"); + if (DataContext == null) throw new NullReferenceException("Failed to set DataContext for MainWindow"); } private async void OnLaunchMinecraftClick(object sender, RoutedEventArgs e) { @@ -29,26 +31,59 @@ public partial class MainWindow : Window if (root == null) return; var vm = DataContext as MainWindowViewModel; - LoadingWindow loading = new(vm.Usernick, vm.SelectedVersion); - loading.Show(root); - await loading.InitLoading(); - loading.Close(); + await LauncherUtils.CreateMinecraftInstance(vm, root); button.Content = "Minecraft launched"; - await loading.RunMinecraft(); } private void OnChooseVersionClick(object sender, RoutedEventArgs e) { + if (sender is not Button button) return; - var button = sender as Button; - if (button == null) return; - - var root = button.GetVisualRoot() as MainWindow; - if (root == null) return; + if (button.GetVisualRoot() is not MainWindow root) return; VersionSelectorWindow selector = new(DataContext as MainWindowViewModel); selector.Show(root); } + private void OnCogPressed(object sender, RoutedEventArgs e) + { + if (sender is not Image img) return; + + if (img.GetVisualRoot() is not MainWindow root) return; + + SettingsWindow settings = new(DataContext as MainWindowViewModel); + settings.Show(root); + } + + private void OnGitlabPressed(object sender, RoutedEventArgs e) + { + string url = "https://gitlab.com/nullmax17/PlombirLauncher"; + try + { + Process.Start(url); + } + catch + { + // hack because of this: https://github.com/dotnet/corefx/issues/10361 + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + url = url.Replace("&", "^&"); + Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start("xdg-open", url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start("open", url); + } + else + { + throw; + } + } + } + } \ No newline at end of file diff --git a/src/LauncherGUI/Views/SettingsWindow.axaml b/src/LauncherGUI/Views/SettingsWindow.axaml new file mode 100644 index 0000000..6b0fddd --- /dev/null +++ b/src/LauncherGUI/Views/SettingsWindow.axaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + +