Skip to content
3 changes: 1 addition & 2 deletions Knossos.NET/Classes/FsoBuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ public async Task<FsoResult> RunFSO(FsoExecType executableType, string cmdline,
output = result;
await cmd.WaitForExitAsync().ConfigureAwait(false);

if (KnUtils.IsLinux && !string.IsNullOrEmpty(stderr))
if (KnUtils.IsLinux && !result.Contains("{"))
{
//Possible missing dependency libs on linux like libfuse for appimage
var errorMsg = $"FSO exited with code {cmd.ExitCode}\n\nStdout:\n{output}\n\nStderr:\n{stderr}";
Expand All @@ -405,7 +405,6 @@ public async Task<FsoResult> RunFSO(FsoExecType executableType, string cmdline,
}
else
{
Log.Add(Log.LogSeverity.Error, "FsoBuild.GetFlagsV1()", stderr);
if (!_flagErrorOneWarn)
{
_flagErrorOneWarn = true;
Expand Down
147 changes: 141 additions & 6 deletions Knossos.NET/Classes/Knossos.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Knossos.NET
{
public static class Knossos
{
public static readonly string AppVersion = "1.3.8";
public static readonly string AppVersion = "1.3.10";
public readonly static string ToolRepoURL = "https://raw.githubusercontent.com/KnossosNET/Knet-Tool-Repo/main/knet_tools.json";
public readonly static string GitHubUpdateRepoURL = "https://api.github.com/repos/KnossosNET/Knossos.NET";
public readonly static string FAQURL = "https://raw.githubusercontent.com/KnossosNET/KNet-General-Resources-Repo/main/communityfaq.json";
Expand Down Expand Up @@ -77,6 +77,134 @@ static Knossos()
inSingleTCMode = CustomLauncher.IsCustomMode;
}

/// <summary>
/// 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
/// </summary>
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.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.");
}
}

/// <summary>
/// Creates and verifies a possible default library path before selecting it.
/// </summary>
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.
}
}
}
}

/// <summary>
/// StartUp sequence
/// </summary>
Expand Down Expand Up @@ -169,16 +297,23 @@ public static async void StartUp(bool isQuickLaunch, bool forceUpdate)
}
}

//Load base path from knossos legacy
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)
{
globalSettings.basePath = KnUtils.GetBasePathFromKnossosLegacy();
DetermineDefaultBasePath();
if (!isQuickLaunch)
OpenQuickSetup();
}

LoadBasePath(isQuickLaunch);

if (globalSettings.basePath == null && !isQuickLaunch && !inSingleTCMode)
OpenQuickSetup();
}
catch(Exception ex)
{
Expand Down
2 changes: 1 addition & 1 deletion Knossos.NET/Models/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Knossos.NET.Models
{
/// <summary>
/// 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)
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions Knossos.NET/ViewModels/GlobalSettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,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
{
Expand Down
1 change: 1 addition & 0 deletions Knossos.NET/ViewModels/Templates/DevModEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ internal void PlayMod(object type)
case "release": Knossos.PlayMod(ActiveVersion,FsoExecType.Release); break;
case "fred2": Knossos.PlayMod(ActiveVersion, FsoExecType.Fred2); break;
case "qtfred": Knossos.PlayMod(ActiveVersion, FsoExecType.QtFred); break;
case "qtfreddebug": Knossos.PlayMod(ActiveVersion, FsoExecType.QtFredDebug); break;
case "debug": Knossos.PlayMod(ActiveVersion, FsoExecType.Debug); break;
case "fred2debug": Knossos.PlayMod(ActiveVersion, FsoExecType.Fred2Debug); break;
}
Expand Down
1 change: 0 additions & 1 deletion Knossos.NET/ViewModels/Windows/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,6 @@ internal void ApplySettings()

public void UpdateBuildInstallButtons(){
DeveloperModView?.UpdateBuildNames(LatestStable, LatestNightly);
QuickSetupViewModel.Instance?.UpdateBuildName(LatestStable);
}

/// <summary>
Expand Down
Loading