From 389dec9c6810fec2104206e0b5f9160068164813 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 23 Aug 2026 13:31:03 -0300 Subject: [PATCH 1/6] change QG on library folder --- Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs | 10 +--------- Knossos.NET/Views/Windows/QuickSetupView.axaml | 9 ++++----- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs b/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs index 260c63de..0e50c7d9 100644 --- a/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs @@ -103,15 +103,7 @@ private void EnterPage2() if (Page2) { - if (LibraryPath == null) - { - await Task.Delay(1000); - EnterPage2(); - } - else - { - CanContinue = true; - } + CanContinue = true; } }); }); diff --git a/Knossos.NET/Views/Windows/QuickSetupView.axaml b/Knossos.NET/Views/Windows/QuickSetupView.axaml index 4db50765..31ef152c 100644 --- a/Knossos.NET/Views/Windows/QuickSetupView.axaml +++ b/Knossos.NET/Views/Windows/QuickSetupView.axaml @@ -36,13 +36,12 @@ - Setting up the Library Folder - First, you must set a Library Folder. Go to the "Settings" tab and under the "KnossosNET" section click on the "Browse" button and choose or create a folder for KnossosNET to use. It is highly recommended to set this as an empty folder in a location with a large amount of available storage. Do not set your Library Folder to a shared or cloud drive (such as OneDrive or Google Drive) because syncing issues will prevent Knossos from downloading mod files correctly. + Knossos Library Folder The KnossosNET Library Folder is where all game and mod data will be saved to. Make sure you always have space available on this drive before installing a new mod or update. Current Library Folder - Go to the "Settings" tab and set the Library Folder to continue. - + This is the current library folder path, if you want to change its location you can go to "Settings" and change it. + KnossosNET is running in portable mode @@ -88,7 +87,7 @@ • Freespace Upgrade MediaVPs - Visual improvements for Freespace 2. It is also used by most, if not all, other FS related mods. This mod has optional visual improvements components (like MV_AdvancedX) and it is recommended to select them all during install. • FreeSpace Port MediaVPs - Visual improvements for the Freespace 1 port. This will also install the Freespace 1 port mod, which gives you access to the full Freespace 1 missions and story. • Silent Threat: Reborn - Fan made replacement and improvement of the original Silent Threat FS1 expansion. The story elements happen after the main FS1 story and before FS2. - Remember that you can always play total conversion mods, which do not require Freespace 2 Retail files. There are many great options, such as Wing Commander Saga, Diaspora, Solaris and more. + Remember that you can always play total conversion mods, which do not require Freespace 2 Retail files. There are many great options, such as Event Horizon, Wing Commander Saga, Diaspora, Solaris and more. This step is optional and you can continue at any time. From dd8a9581eb8ec803bc8fec83028219a33425700f Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 23 Aug 2026 17:24:14 -0300 Subject: [PATCH 2/6] Change page 3, remove page 6 --- Knossos.NET/Models/GlobalSettings.cs | 2 +- .../ViewModels/GlobalSettingsViewModel.cs | 8 + Knossos.NET/ViewModels/MainViewModel.cs | 1 - .../ViewModels/Windows/QuickSetupViewModel.cs | 152 +++--------------- Knossos.NET/Views/GlobalSettingsView.axaml | 8 +- .../Views/Windows/ModInstallView.axaml | 1 - .../Views/Windows/QuickSetupView.axaml | 45 +++--- 7 files changed, 56 insertions(+), 161 deletions(-) diff --git a/Knossos.NET/Models/GlobalSettings.cs b/Knossos.NET/Models/GlobalSettings.cs index e87de9af..fd612d11 100644 --- a/Knossos.NET/Models/GlobalSettings.cs +++ b/Knossos.NET/Models/GlobalSettings.cs @@ -17,7 +17,7 @@ namespace Knossos.NET.Models { /// /// Disabled = No option to compress is ever show - /// Manual = User can select to compress mods manually during install and in mod settings + /// Manual = Mods are not compressed during install; the user can compress them later in mod settings /// Always = Always compress all mods during install, no matter what. /// ModSupport = Compress only if the mod depends on a FSO verson that is higher or equal than the minimal required (23.2.0) /// diff --git a/Knossos.NET/ViewModels/GlobalSettingsViewModel.cs b/Knossos.NET/ViewModels/GlobalSettingsViewModel.cs index 315d28be..722fe8c7 100644 --- a/Knossos.NET/ViewModels/GlobalSettingsViewModel.cs +++ b/Knossos.NET/ViewModels/GlobalSettingsViewModel.cs @@ -166,6 +166,14 @@ internal CompressionSettings ModCompression set { if (modCompression != value) { this.SetProperty(ref modCompression, value); UnCommitedChanges = true; } } } + internal void UpdateModCompressionFromQuickSetup(CompressionSettings value) + { + if (modCompression != value) + { + this.SetProperty(ref modCompression, value, nameof(ModCompression)); + } + } + private int compressionMaxParallelism = 2; internal int CompressionMaxParallelism { diff --git a/Knossos.NET/ViewModels/MainViewModel.cs b/Knossos.NET/ViewModels/MainViewModel.cs index 4b4b15e6..9e84c7a0 100644 --- a/Knossos.NET/ViewModels/MainViewModel.cs +++ b/Knossos.NET/ViewModels/MainViewModel.cs @@ -497,7 +497,6 @@ internal void ApplySettings() public void UpdateBuildInstallButtons() { DeveloperModView?.UpdateBuildNames(LatestStable, LatestNightly); - QuickSetupViewModel.Instance?.UpdateBuildName(LatestStable); } /// diff --git a/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs b/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs index 0e50c7d9..1418058c 100644 --- a/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs @@ -1,9 +1,7 @@ using Avalonia.Controls; -using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using Knossos.NET.Models; using Knossos.NET.Views; -using System.Threading.Tasks; namespace Knossos.NET.ViewModels { @@ -15,8 +13,6 @@ public partial class QuickSetupViewModel : ViewModelBase { private int pageNumber = 1; - [ObservableProperty] - internal bool repoDownloaded = false; [ObservableProperty] internal bool canGoBack = false; [ObservableProperty] @@ -30,10 +26,21 @@ public partial class QuickSetupViewModel : ViewModelBase [ObservableProperty] internal string? libraryPath = null; - [ObservableProperty] - public string latestBuild = string.Empty; - [ObservableProperty] - internal bool buildAvailable = false; + private CompressionSettings modCompression = CompressionSettings.Manual; + internal CompressionSettings ModCompression + { + get { return modCompression; } + set + { + if (modCompression != value) + { + this.SetProperty(ref modCompression, value); + Knossos.globalSettings.modCompression = value; + MainViewModel.Instance?.GlobalSettingsView?.UpdateModCompressionFromQuickSetup(value); + Knossos.globalSettings.Save(false); + } + } + } [ObservableProperty] internal bool page1 = true; @@ -45,44 +52,22 @@ public partial class QuickSetupViewModel : ViewModelBase internal bool page4 = false; [ObservableProperty] internal bool page5 = false; - [ObservableProperty] - internal bool page6 = false; private KnossosWindow? dialog; - public static QuickSetupViewModel? Instance; - public QuickSetupViewModel() { isPortableMode = Knossos.inPortableMode; + libraryPath = Knossos.globalSettings.basePath; + modCompression = Knossos.globalSettings.modCompression; } public QuickSetupViewModel(KnossosWindow dialog) { this.dialog = dialog; isPortableMode = Knossos.inPortableMode; - Instance = this; - UpdateBuildName(MainViewModel.Instance!.LatestStable); - TrackRepoStatus(); - } - - /// - /// Wait until repo_minimal.json has been parsed - /// - private void TrackRepoStatus() - { - Task.Run(async () => - { - do - { - await Task.Delay(1000); - } while (!Nebula.repoLoaded); - - await Dispatcher.UIThread.InvokeAsync(() => - { - RepoDownloaded = Nebula.repoLoaded; - }); - }); + libraryPath = Knossos.globalSettings.basePath; + modCompression = MainViewModel.Instance?.GlobalSettingsView?.ModCompression ?? Knossos.globalSettings.modCompression; } internal void OpenDiscordQuickSetup() @@ -90,48 +75,9 @@ internal void OpenDiscordQuickSetup() KnUtils.OpenBrowserURL(@"https://discord.gg/raSEhVeTGw"); } - /// - /// Wait until the Knossos library path is set - /// private void EnterPage2() { - Task.Run(() => - { - Dispatcher.UIThread.InvokeAsync(async () => - { - LibraryPath = Knossos.globalSettings.basePath; - - if (Page2) - { - CanContinue = true; - } - }); - }); - } - - /// - /// Wait until FSO flags has been loaded - /// - private void EnterPage3() - { - Task.Run(() => - { - Dispatcher.UIThread.InvokeAsync(async () => - { - if (Page3) - { - if (!Knossos.flagDataLoaded) - { - await Task.Delay(1000); - EnterPage3(); - } - else - { - CanContinue = true; - } - } - }); - }); + LibraryPath = Knossos.globalSettings.basePath; } internal void GoBackCommand() @@ -157,56 +103,10 @@ private void SetActivePage() switch(pageNumber) { case 1: CanGoBack = false; CanContinue = true; Page1 = true; Page2 = false; LastPage = false; break; - case 2: CanGoBack = true; CanContinue = false; Page1 = false; Page2 = true; Page3 = false; EnterPage2(); LastPage = false; break; - case 3: CanGoBack = true; CanContinue = false; Page2 = false; Page3 = true; Page4 = false; EnterPage3(); LastPage = false; break; + case 2: CanGoBack = true; CanContinue = true; Page1 = false; Page2 = true; Page3 = false; EnterPage2(); LastPage = false; break; + case 3: CanGoBack = true; CanContinue = true; Page2 = false; Page3 = true; Page4 = false; LastPage = false; break; case 4: CanGoBack = true; CanContinue = true; Page3 = false; Page4 = true; Page5 = false; LastPage = false; break; - case 5: CanGoBack = true; CanContinue = true; Page4 = false; Page5 = true; Page6 = false; LastPage = false; break; - case 6: CanGoBack = true; CanContinue = false; Page5 = false; Page6 = true; LastPage = true; break; - } - } - - public void UpdateBuildName(string stableIn){ - LatestBuild = stableIn; - UpdateBuildInstallButton(); - } - - public void UpdateBuildInstallButton() - { - if (LatestBuild == "") - { - BuildAvailable = false; - } - else - { - var installed = Knossos.GetInstalledBuild("FSO", LatestBuild); - if (installed != null) - { - LatestBuild = ""; - BuildAvailable = false; - } - else - { - BuildAvailable = true; - } - } - } - - public void DownloadLatestStable() - { - if (LatestBuild != ""){ - var stable = new Mod(); - stable.id = "FSO"; - stable.version = LatestBuild; - stable.type = ModType.engine; - stable.stability = "stable"; - - MainViewModel.Instance!.FsoBuildsView!.RelayInstallBuild(stable); - - var installed = Knossos.GetInstalledBuild("FSO", LatestBuild); - if (installed != null){ - LatestBuild = ""; - UpdateBuildInstallButton(); - } + case 5: CanGoBack = true; CanContinue = true; Page4 = false; Page5 = true; LastPage = true; break; } } @@ -215,11 +115,5 @@ public void ClickSettingsButton() MainViewModel.Instance?.ClickOnMenuButton("Settings"); MainViewModel.Instance?.GlobalSettingsView?.ExpandKnossosSection(); } - - public void ClickEngineButton() - { - MainViewModel.Instance?.ClickOnMenuButton("Engine"); - } - } } diff --git a/Knossos.NET/Views/GlobalSettingsView.axaml b/Knossos.NET/Views/GlobalSettingsView.axaml index ca623777..e7a1c490 100644 --- a/Knossos.NET/Views/GlobalSettingsView.axaml +++ b/Knossos.NET/Views/GlobalSettingsView.axaml @@ -14,7 +14,7 @@ - + @@ -61,11 +61,11 @@ Mod Compression - + Disabled Manual - Always - Mod Support + Forced On + Automatic (Recommended) diff --git a/Knossos.NET/Views/Windows/ModInstallView.axaml b/Knossos.NET/Views/Windows/ModInstallView.axaml index 633d548c..1313afe0 100644 --- a/Knossos.NET/Views/Windows/ModInstallView.axaml +++ b/Knossos.NET/Views/Windows/ModInstallView.axaml @@ -69,7 +69,6 @@ - Compress mods during install Install Mod in Developer Mode diff --git a/Knossos.NET/Views/Windows/QuickSetupView.axaml b/Knossos.NET/Views/Windows/QuickSetupView.axaml index 31ef152c..1dbfd423 100644 --- a/Knossos.NET/Views/Windows/QuickSetupView.axaml +++ b/Knossos.NET/Views/Windows/QuickSetupView.axaml @@ -11,7 +11,7 @@ Icon="/Assets/knossos-icon.ico" Topmost="True" WindowStartupLocation="CenterOwner" - Title="Quick Setup Guide" + Title="Quick Start Guide" SizeToContent="WidthAndHeight" MaxWidth="800" MinHeight="400" @@ -28,6 +28,7 @@ Welcome To Knossos.NET This quick setup guide will help you through the basics of configuring the KnossosNET launcher for the first time. If you already know how to configure the launcher you can close this window. + Every step in this guide is optional, so you can continue or close the guide at any time. Note, you can reopen this guide at any time, just go to the "Settings" tab and click the "Quick Setup Guide" button. If you ever need assistance with KnossosNET please ask on the Discord channel linked below. @@ -36,7 +37,7 @@ - Knossos Library Folder + Knossos Library Folder (Optional) The KnossosNET Library Folder is where all game and mod data will be saved to. Make sure you always have space available on this drive before installing a new mod or update. Current Library Folder @@ -54,28 +55,30 @@ - Download an FSO engine build - Wait for repo_minimal.json to finish downloading before you continue... - - Now you need a game engine build, which are known as "FSO Builds". These builds are what mods run on, and KnossosNET also uses it to get and display system data. This is why you are not going to be able to set most of the settings in the "Settings" tab before downloading one. - Click the button below to download the latest stable build, which is what most casual players use. You can also go to the "Engine" tab, and pick a specific build. The most recent build should be always the top one on the list. - Go to the "Engine" tab, select "Stable Builds" and download the newest stable, it should be always the top one on the list. - - Engine build detected! - Keep in mind that some mods may download and run on different versions of the FSO engine. This is because some mods cannot run on newer builds or they require a specific FSO build version. You can always change the FSO build used by a mod by opening the "Mod Settings" on the mod card, but keep in mind not all mods can run on all engine builds. - + Mod Compression (Optional) + KnossosNET can compress supported mod files in your library as mods are installed. This can reduce their size on disk, but compression requires additional processing and can make installations take longer. + Choose how KnossosNET handles mod compression: + + Disabled + Manual + Forced On + Automatic (Recommended) + + Disabled: Mod compression is unavailable. + Manual: Mods are not compressed during installation. To compress a mod, install it first, open its individual Mod Settings, and use the compression option there. + Automatic (Recommended): Mods are compressed during installation only when they meet the minimum FSO build requirements for mod compression. + Forced On: All non-developer mods are compressed during installation. + You can change this option at any time in "Settings" under the "KnossosNET Settings" section. + Freespace 2 Retail (Optional) - In order to have access to Freespace 1 and 2 content and visual improvements you need to install Freespace 2 Retail in KnossosNET. If you do not install Freespace 2 Retail, then any content that needs the full Freespace 2 retail files will not be displayed on the "Explore" tab. + In order to have access to Freespace 1 and 2 content and visual improvements you need to install Freespace 2 Retail game data in KnossosNET. If you do not install Freespace 2 Retail, then any content that needs the full Freespace 2 retail files will not be displayed on the "Explore" tab. If you do not have the retail FS2 installed into KnossosNET you can still play total conversion mods, which are mods that are completely standalone and do not depend on any of the Freespace content. To install Freespace 2 go to the "Settings" tab and open the "FS2 Retail Installer" button under the "KnossosNET Settings" section. Then follow the instructions there. If you already have FS2 installed this button is not available. - This step is optional and you can continue at any time. @@ -88,21 +91,13 @@ • FreeSpace Port MediaVPs - Visual improvements for the Freespace 1 port. This will also install the Freespace 1 port mod, which gives you access to the full Freespace 1 missions and story. • Silent Threat: Reborn - Fan made replacement and improvement of the original Silent Threat FS1 expansion. The story elements happen after the main FS1 story and before FS2. Remember that you can always play total conversion mods, which do not require Freespace 2 Retail files. There are many great options, such as Event Horizon, Wing Commander Saga, Diaspora, Solaris and more. - This step is optional and you can continue at any time. - - - - - Finishing - Finally, before launching a mod go to the "Settings" tab and configure video and audio settings, as well as any joysticks you may have installed. - - + From 0b1dbb702c80421038d357832fe87822ea738e70 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 23 Aug 2026 17:34:45 -0300 Subject: [PATCH 3/6] finish setup guide --- .../ViewModels/Windows/QuickSetupViewModel.cs | 12 +++++++++++- Knossos.NET/Views/GlobalSettingsView.axaml | 2 +- Knossos.NET/Views/Windows/QuickSetupView.axaml | 13 +++++++------ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs b/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs index 1418058c..e9a625a5 100644 --- a/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs @@ -26,6 +26,9 @@ public partial class QuickSetupViewModel : ViewModelBase [ObservableProperty] internal string? libraryPath = null; + [ObservableProperty] + internal string retailFs2Status = string.Empty; + private CompressionSettings modCompression = CompressionSettings.Manual; internal CompressionSettings ModCompression { @@ -80,6 +83,13 @@ private void EnterPage2() LibraryPath = Knossos.globalSettings.basePath; } + private void EnterPage4() + { + RetailFs2Status = Knossos.retailFs2RootFound + ? "Current Status: Freespace 2 Game Data is Installed" + : "Current Status: Freespace 2 Game Data is NOT Installed"; + } + internal void GoBackCommand() { pageNumber--; @@ -105,7 +115,7 @@ private void SetActivePage() case 1: CanGoBack = false; CanContinue = true; Page1 = true; Page2 = false; LastPage = false; break; case 2: CanGoBack = true; CanContinue = true; Page1 = false; Page2 = true; Page3 = false; EnterPage2(); LastPage = false; break; case 3: CanGoBack = true; CanContinue = true; Page2 = false; Page3 = true; Page4 = false; LastPage = false; break; - case 4: CanGoBack = true; CanContinue = true; Page3 = false; Page4 = true; Page5 = false; LastPage = false; break; + case 4: CanGoBack = true; CanContinue = true; Page3 = false; Page4 = true; Page5 = false; EnterPage4(); LastPage = false; break; case 5: CanGoBack = true; CanContinue = true; Page4 = false; Page5 = true; LastPage = true; break; } } diff --git a/Knossos.NET/Views/GlobalSettingsView.axaml b/Knossos.NET/Views/GlobalSettingsView.axaml index e7a1c490..a0df7a99 100644 --- a/Knossos.NET/Views/GlobalSettingsView.axaml +++ b/Knossos.NET/Views/GlobalSettingsView.axaml @@ -65,7 +65,7 @@ Disabled Manual Forced On - Automatic (Recommended) + Automatic diff --git a/Knossos.NET/Views/Windows/QuickSetupView.axaml b/Knossos.NET/Views/Windows/QuickSetupView.axaml index 1dbfd423..94c7943f 100644 --- a/Knossos.NET/Views/Windows/QuickSetupView.axaml +++ b/Knossos.NET/Views/Windows/QuickSetupView.axaml @@ -37,7 +37,7 @@ - Knossos Library Folder (Optional) + Knossos Library Folder The KnossosNET Library Folder is where all game and mod data will be saved to. Make sure you always have space available on this drive before installing a new mod or update. Current Library Folder @@ -55,18 +55,18 @@ - Mod Compression (Optional) + Mod Compression KnossosNET can compress supported mod files in your library as mods are installed. This can reduce their size on disk, but compression requires additional processing and can make installations take longer. Choose how KnossosNET handles mod compression: Disabled Manual Forced On - Automatic (Recommended) + Automatic Disabled: Mod compression is unavailable. Manual: Mods are not compressed during installation. To compress a mod, install it first, open its individual Mod Settings, and use the compression option there. - Automatic (Recommended): Mods are compressed during installation only when they meet the minimum FSO build requirements for mod compression. + Automatic: Mods are compressed during installation only when they meet the minimum FSO build requirements for mod compression. Forced On: All non-developer mods are compressed during installation. You can change this option at any time in "Settings" under the "KnossosNET Settings" section. @@ -74,7 +74,8 @@ - Freespace 2 Retail (Optional) + Installing Freespace 2 Retail + In order to have access to Freespace 1 and 2 content and visual improvements you need to install Freespace 2 Retail game data in KnossosNET. If you do not install Freespace 2 Retail, then any content that needs the full Freespace 2 retail files will not be displayed on the "Explore" tab. If you do not have the retail FS2 installed into KnossosNET you can still play total conversion mods, which are mods that are completely standalone and do not depend on any of the Freespace content. To install Freespace 2 go to the "Settings" tab and open the "FS2 Retail Installer" button under the "KnossosNET Settings" section. Then follow the instructions there. If you already have FS2 installed this button is not available. @@ -83,7 +84,7 @@ - Installing mods (Optional) + Installing mods and total conversions The "Freespace" tab is where the most relevant mods to Freespace, including Freespace 2 retail, Freespace 1 and their graphics upgrades are listed for easy access. If you are just starting to KnossosNET we recommend you start there. The "Play" tab is where all your installed mods are displayed, while the "Explore" tab shows only uninstalled mods. If you have installed Freespace 2 Retail, the FS2 retail mod card will already be added to your "Play" tab, but if you click "Play" right now you will be playing Freespace 2 in only its original 1999 glory. At this point you are probably looking for the visual improvements, so go to the "Explore" tab and lets download and install some mods! The following mods are some of the main projects related to improving visuals and Freespace story: From fb35c809a1f50a86e6a0b7a37ec218d591283349 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 23 Aug 2026 18:09:35 -0300 Subject: [PATCH 4/6] Set default library path in new installs --- Knossos.NET/Classes/Knossos.cs | 135 ++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 9 deletions(-) diff --git a/Knossos.NET/Classes/Knossos.cs b/Knossos.NET/Classes/Knossos.cs index c18bc571..f2d9ce3d 100644 --- a/Knossos.NET/Classes/Knossos.cs +++ b/Knossos.NET/Classes/Knossos.cs @@ -78,6 +78,129 @@ static Knossos() inSingleTCMode = CustomLauncher.IsCustomMode; } + /// + /// Run only on first installs, determines the default first library path by OS + /// + private static void DetermineDefaultBasePath() + { + //Load base path from knossos legacy, if it exists + var legacyBasePath = KnUtils.GetBasePathFromKnossosLegacy(); + if (Directory.Exists(legacyBasePath) && TrySetDefaultBasePath(legacyBasePath)) + { + Log.Add(Log.LogSeverity.Information, "Knossos.DetermineDefaultBasePath()", $"Loading library path '{globalSettings.basePath}' from Knossos Legacy."); + globalSettings.Save(false); + return; + } + + var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + + if (KnUtils.IsAndroid) + { + TrySetDefaultBasePath(AndroidHelper.GetDefaultLibraryDir()); + } + else if (KnUtils.IsWindows) + { + var systemRoot = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)); + if (string.IsNullOrWhiteSpace(systemRoot)) + systemRoot = @"C:\"; + + TrySetDefaultBasePath(Path.Combine(systemRoot, "Games", "KnossosNET", "FreespaceOpen")); + + if (globalSettings.basePath == null) + { + var publicProfile = Environment.GetEnvironmentVariable("PUBLIC"); + if (string.IsNullOrWhiteSpace(publicProfile)) + { + var commonDocuments = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments); + if (!string.IsNullOrWhiteSpace(commonDocuments)) + publicProfile = Directory.GetParent(commonDocuments)?.FullName; + } + + if (!string.IsNullOrWhiteSpace(publicProfile)) + TrySetDefaultBasePath(Path.Combine(publicProfile, "KnossosNET", "FreespaceOpen")); + } + } + else if (KnUtils.IsMacOS) + { + TrySetDefaultBasePath(Path.Combine(userProfile, "Library", "Application Support", "io.github.KnossosNET.Knossos_NET", "FreespaceOpen")); + } + else if (KnUtils.IsLinux) + { + TrySetDefaultBasePath(Path.Combine(userProfile, "KnossosNET", "FreespaceOpen")); + } + + // General fallbacks for an unknown OS, or when the preferred OS path is not writable. + if (globalSettings.basePath == null && !string.IsNullOrWhiteSpace(userProfile)) + TrySetDefaultBasePath(Path.Combine(userProfile, "KnossosNET", "FreespaceOpen")); + + if (globalSettings.basePath == null) + { + var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + if (!string.IsNullOrWhiteSpace(localAppData)) + TrySetDefaultBasePath(Path.Combine(localAppData, "KnossosNET", "FreespaceOpen")); + } + + if (globalSettings.basePath == null) + TrySetDefaultBasePath(Path.Combine(KnUtils.GetKnossosDataFolderPath(), "FreespaceOpen")); + + if (globalSettings.basePath != null) + { + Log.Add(Log.LogSeverity.Information, "Knossos.DetermineDefaultBasePath()", $"Choosing '{globalSettings.basePath}' as default library path."); + globalSettings.Save(false); + } + else + { + Log.Add(Log.LogSeverity.Error, "Knossos.DetermineDefaultBasePath()", "Unable to find a writable default library path."); + } + } + + /// + /// Creates and verifies a possible default library path before selecting it. + /// + private static bool TrySetDefaultBasePath(string? path) + { + if (string.IsNullOrWhiteSpace(path)) + return false; + + string? writeTestPath = null; + try + { + var fullPath = Path.GetFullPath(path); + Directory.CreateDirectory(fullPath); + + writeTestPath = Path.Combine(fullPath, $".knossos_write_test_{Guid.NewGuid():N}.tmp"); + using (var writeTest = new FileStream(writeTestPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + { + writeTest.WriteByte(0); + writeTest.Flush(true); + } + + File.Delete(writeTestPath); + writeTestPath = null; + globalSettings.basePath = fullPath; + return true; + } + catch (Exception ex) + { + Log.Add(Log.LogSeverity.Warning, "Knossos.TrySetDefaultBasePath()", $"Cannot use '{path}' as the default library path: {ex.Message}"); + return false; + } + finally + { + if (writeTestPath != null) + { + try + { + File.Delete(writeTestPath); + } + catch + { + // Best-effort cleanup of the temporary write test. + } + } + } + } + /// /// StartUp sequence /// @@ -153,20 +276,14 @@ public static async void StartUp(bool isQuickLaunch, bool forceUpdate) } } - //Load base path from knossos legacy - if (globalSettings.basePath == null && KnUtils.IsAndroid) - { - globalSettings.basePath = AndroidHelper.GetDefaultLibraryDir(); - } if (globalSettings.basePath == null && !inSingleTCMode) { - globalSettings.basePath = KnUtils.GetBasePathFromKnossosLegacy(); + DetermineDefaultBasePath(); + if (!isQuickLaunch) + OpenQuickSetup(); } LoadBasePath(isQuickLaunch); - - if (globalSettings.basePath == null && !isQuickLaunch && !inSingleTCMode) - OpenQuickSetup(); } catch(Exception ex) { From 6f3483eec6b83ece9f425ac3eaa76185aabbe569 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 23 Aug 2026 18:28:55 -0300 Subject: [PATCH 5/6] warn on missing folder --- Knossos.NET/Classes/Knossos.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Knossos.NET/Classes/Knossos.cs b/Knossos.NET/Classes/Knossos.cs index f2d9ce3d..6efd3454 100644 --- a/Knossos.NET/Classes/Knossos.cs +++ b/Knossos.NET/Classes/Knossos.cs @@ -79,7 +79,16 @@ static Knossos() } /// - /// Run only on first installs, determines the default first library path by OS + /// Run only on first install, determines the default first library path by OS + /// Write checks are done to make sure we can write to this folder + /// + /// Rutes: + /// -First try to look and use a library from Knossos Legacy + /// -Windows: C:\Games\KnossosNET\FreespaceOpen; If not writtable: %PUBLIC%\KnossosNET\FreespaceOpen + /// -MacOS: ~/Library/Application Support/io.github.KnossosNET.Knossos_NET/FreespaceOpen + /// -Linux: ~/KnossosNET/FreespaceOpen + /// -Android: {internal storage}/Android/data/com.knossosnet.knossosnet/files/library + /// Fallbacks: {user profile}\KnossosNET\FreespaceOpen, then {LocalApplicationData}\KnossosNET\FreespaceOpen /// private static void DetermineDefaultBasePath() { @@ -276,6 +285,15 @@ public static async void StartUp(bool isQuickLaunch, bool forceUpdate) } } + if(globalSettings.basePath != null && !isQuickLaunch && !Directory.Exists(globalSettings.basePath)) + { + //Reset and warn + Dispatcher.UIThread.Invoke(() => { + MessageBox.Show(MainWindow.instance, $"The previusly selected library folder:\n\n'{globalSettings.basePath}'\n\nNot longer exists, the library folder will be reset back to default.", "Library folder not found" , MessageBox.MessageBoxButtons.OK); + }); + globalSettings.basePath = null; + } + if (globalSettings.basePath == null && !inSingleTCMode) { DetermineDefaultBasePath(); From edd2b0024cdbbf1cbee2979915cddf3b193467f6 Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 23 Aug 2026 18:54:53 -0300 Subject: [PATCH 6/6] revert removal of manual compression option --- Knossos.NET/Views/Windows/ModInstallView.axaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Knossos.NET/Views/Windows/ModInstallView.axaml b/Knossos.NET/Views/Windows/ModInstallView.axaml index 1313afe0..055e0b13 100644 --- a/Knossos.NET/Views/Windows/ModInstallView.axaml +++ b/Knossos.NET/Views/Windows/ModInstallView.axaml @@ -69,6 +69,9 @@ + + Compress mods during install + Install Mod in Developer Mode