Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Knossos.NET/Classes/FsoBuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ public async Task<FsoResult> RunFSO(FsoExecType executableType, string cmdline,
fso.StartInfo.UseShellExecute = false;
if (workingFolder != null)
fso.StartInfo.WorkingDirectory = workingFolder;
if(Knossos.inPortableMode && Knossos.globalSettings.portableFsoPreferences)
{
var prefPath = Path.Combine(KnUtils.KnetFolderPath!, "kn_portable", "HardLightProductions", "FreeSpaceOpen") + Path.DirectorySeparatorChar;
Log.Add(Log.LogSeverity.Information, "FsoBuild.RunFSO()", "Used preferences path: " + prefPath);
fso.StartInfo.EnvironmentVariables.Add("FSO_PREFERENCES_PATH", prefPath);
}
if (Knossos.globalSettings.envVars != "")
{
foreach (var envVar in Knossos.globalSettings.envVars.Split(","))
Expand Down Expand Up @@ -343,6 +349,10 @@ public async Task<FsoResult> RunFSO(FsoExecType executableType, string cmdline,
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.StandardOutputEncoding = new UTF8Encoding(false);
cmd.StartInfo.WorkingDirectory = folderPath;
if (Knossos.inPortableMode && Knossos.globalSettings.portableFsoPreferences)
{
cmd.StartInfo.EnvironmentVariables.Add("FSO_PREFERENCES_PATH", Path.Combine(KnUtils.KnetFolderPath!, "kn_portable", "HardLightProductions", "FreeSpaceOpen") + Path.DirectorySeparatorChar);
}
cmd.Start();
string result = cmd.StandardOutput.ReadToEnd();
output = result;
Expand Down
38 changes: 30 additions & 8 deletions Knossos.NET/Classes/KnUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ public static string? KnetFolderPath
{
return Path.GetDirectoryName(KnUtils.AppImagePath);
}
else if (IsMacOS && WasInstallerUsed())
{
var execFullPath = Environment.ProcessPath;
var cutOff = execFullPath!.IndexOf(".app") + 4;
var realName = execFullPath![..cutOff];
return Path.GetDirectoryName(realName);
}
else
{
return AppDomain.CurrentDomain.BaseDirectory;
Expand All @@ -112,7 +119,14 @@ public static string? KnetFolderPath
/// <returns>fullpath as a string</returns>
public static string GetKnossosDataFolderPath()
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create), "KnossosNET");
if (!Knossos.inPortableMode)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create), "KnossosNET");
}
else
{
return Path.Combine(KnetFolderPath!, "kn_portable", "KnossosNET"); //If inPortableMode = true, KnetFolderPath is not null
}
}

/// <summary>
Expand All @@ -124,20 +138,28 @@ public static string GetKnossosDataFolderPath()
/// <returns>fullpath as string</returns>
public static string GetFSODataFolderPath()
{
if (!string.IsNullOrEmpty(fsoPrefPath))
if (Knossos.inPortableMode && Knossos.globalSettings.portableFsoPreferences)
{
return fsoPrefPath;
return Path.Combine(KnetFolderPath!, "kn_portable", "HardLightProductions", "FreeSpaceOpen"); //If inPortableMode = true, KnetFolderPath is not null
}
else
{
if (KnUtils.isMacOS){
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "HardLightProductions", "FreeSpaceOpen");
if (!string.IsNullOrEmpty(fsoPrefPath))
{
return fsoPrefPath;
}
if(IsLinux)
else
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "HardLightProductions", "FreeSpaceOpen");
if (KnUtils.isMacOS)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "HardLightProductions", "FreeSpaceOpen");
}
if (IsLinux)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "HardLightProductions", "FreeSpaceOpen");
}
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create), "HardLightProductions", "FreeSpaceOpen");
}
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create), "HardLightProductions", "FreeSpaceOpen");
}

}
Expand Down
67 changes: 65 additions & 2 deletions Knossos.NET/Classes/Knossos.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ public static class Knossos
public static bool flagDataLoaded = false;
private static object? ttsObject = null;
private static bool forceUpdateDownload = false; //Only intended to test the update system!
public static bool inPortableMode { get; private set; } = false;
public static bool isKnDataFolderReadOnly { get; private set; } = false;

/// <summary>
/// Static constructor
/// </summary>
static Knossos()
{
try
{
//We are in portable mode? if so set everything up ahead of all else
var pathToExec = KnUtils.KnetFolderPath;
if (pathToExec != null)
{
if (Directory.Exists(Path.Combine(pathToExec, "kn_portable")))
{
inPortableMode = true;
}
}
}
catch (Exception ex)
{
//At this stage we can only log to console
Log.WriteToConsole("Knossos() - " + ex.Message);
}
}

/// <summary>
/// StartUp sequence
Expand Down Expand Up @@ -58,15 +84,30 @@ public static async void StartUp(bool isQuickLaunch, bool forceUpdate)
}
catch (Exception ex)
{
isKnDataFolderReadOnly = true;
Log.Add(Log.LogSeverity.Error, "Knossos.StartUp()", ex);
if (MainWindow.instance != null)
{
await MessageBox.Show(MainWindow.instance, "Unable to write to KnossosNET data folder.", "KnossosNET Error", MessageBox.MessageBoxButtons.OK);
await MessageBox.Show(MainWindow.instance, "Unable to write to KnossosNET data folder:\n'"+ KnUtils.GetKnossosDataFolderPath()+"'\nSome functions may not work correctly.", "KnossosNET Error", MessageBox.MessageBoxButtons.OK);
}
}

Log.Add(Log.LogSeverity.Information, "Knossos.StartUp()", "=== KnossosNET v" + AppVersion + " Start ===");

if (inPortableMode)
{
Log.Add(Log.LogSeverity.Information, "Knossos.StartUp()", "Running in PORTABLE MODE.");
try
{
Directory.CreateDirectory(Path.Combine(KnUtils.KnetFolderPath!, "kn_portable", "HardLightProductions", "FreeSpaceOpen"));
Directory.CreateDirectory(Path.Combine(KnUtils.KnetFolderPath!, "kn_portable", "Library"));
}
catch (Exception ex)
{
Log.Add(Log.LogSeverity.Error, "Knossos.Startup()", ex);
}
}

//Load language files
Lang.LoadFiles();

Expand Down Expand Up @@ -1157,7 +1198,7 @@ public static async void PlayMod(Mod mod, FsoExecType fsoExecType, bool standalo
cmdline += " -mod " + modFlag;
}

Log.Add(Log.LogSeverity.Information, "Knossos.PlayMod()", "Used cmdLine : " + cmdline);


if (MainWindow.instance != null && globalSettings.warnNewSettingsSystem)
{
Expand Down Expand Up @@ -1193,6 +1234,28 @@ await Dispatcher.UIThread.InvokeAsync(async () => {
}
}

//Portable mode and limitations in unsupported fso versions
if (inPortableMode && globalSettings.portableFsoPreferences)
{
try
{
var fsoVersion = new SemanticVersion(fsoBuild.version);
var newPortableModeVersion = new SemanticVersion("24.3.0-20241211");
if (fsoVersion < newPortableModeVersion)
{
cmdline = "-portable_mode " + cmdline;
//older portable mode uses working path to pickup the .ini and store pilots
globalSettings.WriteFS2IniValues(Path.Combine(rootPath, "fs2_open.ini"));
}
}
catch(Exception ex)
{
Log.Add(Log.LogSeverity.Error, "Knossos.PlayMod()", ex);
}
}

Log.Add(Log.LogSeverity.Information, "Knossos.PlayMod()", "Used cmdLine : " + cmdline);

//Launch FSO!!!
var fsoResult = await fsoBuild.RunFSO(fsoExecType, cmdline, rootPath, false);

Expand Down
27 changes: 23 additions & 4 deletions Knossos.NET/Models/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ public MainWindowViewModel.SortType sortType
public string pxoLogin { get; set; } = "";
[JsonIgnore]
public string pxoPassword { get; set; } = "";
[JsonPropertyName("portable_fso_preferences")]
public bool portableFsoPreferences { get; set; } = true;

/* Developer Settings */
[JsonPropertyName("no_system_cmd")]
Expand Down Expand Up @@ -667,6 +669,7 @@ public void Load()
warnNewSettingsSystem = tempSettings.warnNewSettingsSystem;
mainMenuOpen = tempSettings.mainMenuOpen;
sortType = tempSettings.sortType;
portableFsoPreferences = tempSettings.portableFsoPreferences;

ReadFS2IniValues();
Log.Add(Log.LogSeverity.Information, "GlobalSettings.Load()", "Global settings have been loaded");
Expand All @@ -684,13 +687,19 @@ public void Load()
{
Log.Add(Log.LogSeverity.Error, "GlobalSettings.Load()", ex);
}
if(Knossos.inPortableMode)
{
basePath = Path.Combine(KnUtils.KnetFolderPath!, "kn_portable", "Library");
}
}

/// <summary>
/// Save setting data to the fs2_open.ini
/// Stops the ini-watcher if it was enabled and re-enables it to avoid triggering a read
/// Optional: Specific path to write the .ini to, need to be FULL PATH
/// </summary>
public void WriteFS2IniValues()
/// <param name="customPath"></param>
public void WriteFS2IniValues(string? customFullPath = null)
{
try
{
Expand Down Expand Up @@ -850,10 +859,20 @@ public void WriteFS2IniValues()
wasWatchingIni = iniWatcher.EnableRaisingEvents;
iniWatcher.EnableRaisingEvents = false;
}
parser.WriteFile(KnUtils.GetFSODataFolderPath() + Path.DirectorySeparatorChar + "fs2_open.ini", data, new UTF8Encoding(false));
if(iniWatcher!= null && wasWatchingIni)
if (customFullPath == null)
{
parser.WriteFile(KnUtils.GetFSODataFolderPath() + Path.DirectorySeparatorChar + "fs2_open.ini", data, new UTF8Encoding(false));
Log.Add(Log.LogSeverity.Information, "GlobalSettings.WriteFS2IniValues", "Writen ini: " + KnUtils.GetFSODataFolderPath() + Path.DirectorySeparatorChar + "fs2_open.ini");
}
else
{

parser.WriteFile(customFullPath, data, new UTF8Encoding(false));
Log.Add(Log.LogSeverity.Information, "GlobalSettings.WriteFS2IniValues", "Writen ini: " + customFullPath);
}

if (iniWatcher!= null && wasWatchingIni)
iniWatcher.EnableRaisingEvents = true;
Log.Add(Log.LogSeverity.Information, "GlobalSettings.WriteFS2IniValues","Writen ini: "+ KnUtils.GetFSODataFolderPath() + Path.DirectorySeparatorChar + "fs2_open.ini");
}
catch (Exception ex)
{
Expand Down
9 changes: 6 additions & 3 deletions Knossos.NET/Models/Log.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ public static void Add(LogSeverity logSeverity, string from, string data)
Task.Run(async () => {
try
{
await WaitForFileAccess(LogFilePath);
using (var writer = new StreamWriter(LogFilePath, true))
if (!Knossos.isKnDataFolderReadOnly)
{
writer.WriteLine(logString, Encoding.UTF8);
await WaitForFileAccess(LogFilePath);
using (var writer = new StreamWriter(LogFilePath, true))
{
writer.WriteLine(logString, Encoding.UTF8);
}
}
}
catch (Exception ex)
Expand Down
19 changes: 17 additions & 2 deletions Knossos.NET/ViewModels/GlobalSettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public partial class GlobalSettingsViewModel : ViewModelBase
private const long speed10MB = 170000000;

/* For display only */

[ObservableProperty]
internal bool isPortableMode = false;
[ObservableProperty]
internal bool flagDataLoaded = false;
[ObservableProperty]
Expand All @@ -61,7 +62,6 @@ public partial class GlobalSettingsViewModel : ViewModelBase
internal bool isAVX2 = false;

/* Knossos Settings */

[ObservableProperty]
internal string basePath = string.Empty; //When this is changed settings are saved immediately.

Expand Down Expand Up @@ -500,6 +500,14 @@ internal string EnvVars
set { if (envVars != value) { this.SetProperty(ref envVars, value); UnCommitedChanges = true; } }
}

/* MISC */
private bool portableFsoPreferences = true;
internal bool PortableFsoPreferences
{
get { return portableFsoPreferences; }
set { if (portableFsoPreferences != value) { this.SetProperty(ref portableFsoPreferences, value); UnCommitedChanges = true; } }
}

internal string globalCmd = string.Empty;
// In order to have hidden dev options, we need a setter for globalCMD
public string GlobalCmd
Expand All @@ -522,6 +530,7 @@ public string GlobalCmd

public GlobalSettingsViewModel()
{
isPortableMode = Knossos.inPortableMode;
}

/// <summary>
Expand Down Expand Up @@ -1037,6 +1046,9 @@ public void LoadData()
//Multi Port
MultiPort = Knossos.globalSettings.multiPort;

//MISC
PortableFsoPreferences = Knossos.globalSettings.portableFsoPreferences;

UnCommitedChanges = false;
}

Expand Down Expand Up @@ -1364,6 +1376,9 @@ internal void SaveCommand()
//Multi port
Knossos.globalSettings.multiPort = MultiPort;

//MISC
Knossos.globalSettings.portableFsoPreferences = PortableFsoPreferences;

Knossos.globalSettings.Save();
UnCommitedChanges = false;
}
Expand Down
7 changes: 6 additions & 1 deletion Knossos.NET/ViewModels/Windows/QuickSetupViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public partial class QuickSetupViewModel : ViewModelBase
[ObservableProperty]
internal bool lastPage = false;

[ObservableProperty]
internal bool isPortableMode = false;

[ObservableProperty]
internal string? libraryPath = null;

Expand All @@ -49,12 +52,14 @@ public partial class QuickSetupViewModel : ViewModelBase
public static QuickSetupViewModel? Instance;

public QuickSetupViewModel()
{
{
isPortableMode = Knossos.inPortableMode;
}

public QuickSetupViewModel(Window dialog)
{
this.dialog = dialog;
isPortableMode = Knossos.inPortableMode;
Instance = this;
UpdateBuildName(MainWindowViewModel.Instance!.LatestStable);
TrackRepoStatus();
Expand Down
7 changes: 6 additions & 1 deletion Knossos.NET/Views/GlobalSettingsView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<Grid ColumnDefinitions="Auto,Auto,Auto" Margin="7,10,0,0">
<TextBlock Grid.Column="0" VerticalAlignment="Center" Width="200">Library Folder </TextBlock>
<TextBox Text="{Binding BasePath}" Margin="10,0,0,0" Grid.Column="1" IsReadOnly="True" Width="500"></TextBox>
<Button Margin="5,0,0,0" Grid.Column="2" Classes="Quaternary" Command="{Binding BrowseFolderCommand}">Browse</Button>
<Button IsVisible="{Binding !IsPortableMode}" Margin="5,0,0,0" Grid.Column="2" Classes="Quaternary" Command="{Binding BrowseFolderCommand}">Browse</Button>
</Grid>
<!-- Lib Info -->
<Grid ColumnDefinitions="Auto,Auto,Auto" RowDefinitions="Auto, Auto" Margin="6,10,0,0">
Expand Down Expand Up @@ -369,6 +369,11 @@
<ComboBoxItem>Polish</ComboBoxItem>
</ComboBox>
</Grid>
<!-- Portable FSO Preferences -->
<WrapPanel IsVisible="{Binding IsPortableMode}">
<Label Margin="4,5,0,0" Width="200" ToolTip.Tip="Store FSO pilots and settings in a portable location. Only if the launcher is in portable mode">Portable FSO Data</Label>
<ToggleSwitch Margin="11,0,0,0" IsChecked="{Binding PortableFsoPreferences}"></ToggleSwitch>
</WrapPanel>
<!-- Sys Info -->
<WrapPanel Margin="9,0,0,0">
<TextBlock VerticalAlignment="Center" Width="201">Detected Build Settings </TextBlock>
Expand Down
Loading