From a505d48a4c7807d8d590b1e3f483342ad05e5657 Mon Sep 17 00:00:00 2001 From: Maplewheels Date: Sun, 8 Feb 2026 20:23:30 -0500 Subject: [PATCH] - Loading/Saving for Settings via console. --- .../SharedSource/DebugConsole.cs | 4 + .../LuaCs/Data/ServicesConfigData.cs | 139 +----------------- .../SharedSource/LuaCs/LuaCsSetup.cs | 2 + .../LuaCs/_Services/ConfigService.cs | 23 ++- .../LuaCs/_Services/LoggerService.cs | 7 +- .../LuaCs/_Services/StorageService.cs | 11 +- 6 files changed, 40 insertions(+), 146 deletions(-) diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index 79fcd8002..51cf0444f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -2385,6 +2385,10 @@ namespace Barotrauma if (setting.TrySetValue(valueString)) { NewMessage($"Set config {internalName} value to {valueString}", Color.Green); + if (GameMain.LuaCs.ConfigService.SaveConfigValue(setting) is { IsFailed: true } res) + { + NewMessage($"Failed to save new config data to disk. Reasons: {res.ToString()}"); + } } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs index 87cfdf29c..2601e1826 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs @@ -25,31 +25,14 @@ public interface IStorageServiceConfig : IService #if CLIENT string TempDownloadsDirectory { get; } #endif - - //ReadOnlyCollection SafeIOReadDirectories { get; } - //ReadOnlyCollection SafeIOWriteDirectories { get; } - IEnumerable GlobalIOReadWhitelist(); - IEnumerable GlobalIOWriteWhitelist(); - - bool IOReadWhiteListContains(string filePath); - bool IOWriteWhiteListContains(string filePath); - string LocalDataSavePath { get; } string LocalDataPathRegex { get; } string LocalPackageDataPath { get; } - public string RunLocation { get; } - bool GlobalSafeIOEnabled { get; } } -internal interface IStorageServiceConfigUpdate +public record StorageServiceConfig : IStorageServiceConfig { - public FluentResults.Result SetSafeReadFilePaths(string[] filePaths); - public FluentResults.Result SetSafeWriteFilePaths(string[] filePaths); -} - -public record StorageServiceConfig : IStorageServiceConfig, IStorageServiceConfigUpdate -{ - private static readonly string ExecutionLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.CleanUpPath()); + private static readonly string ExecutionLocation = Directory.GetCurrentDirectory().CleanUpPathCrossPlatform(); public string LocalModsDirectory { get; init; } = System.IO.Path.GetFullPath(ContentPackage.LocalModsDir).CleanUpPath(); public string WorkshopModsDirectory { get; init; } = System.IO.Path.GetFullPath(ContentPackage.WorkshopModsDir).CleanUpPath(); @@ -60,125 +43,11 @@ public record StorageServiceConfig : IStorageServiceConfig, IStorageServiceConfi #if CLIENT public string TempDownloadsDirectory { get; init; } = System.IO.Path.GetFullPath(ModReceiver.DownloadFolder).CleanUpPath(); #endif - - private readonly AsyncReaderWriterLock _safeIOReadLock = new(); - private readonly AsyncReaderWriterLock _safeIOWriteLock = new(); - private readonly ConcurrentDictionary _safeIOReadFilePaths = new(); - - private readonly ConcurrentDictionary _safeIOWriteFilePaths = new(); - - public IEnumerable GlobalIOReadWhitelist() - { - using var lck = _safeIOReadLock.AcquireReaderLock().GetAwaiter().GetResult(); - - if (_safeIOReadFilePaths.Count == 0) - { - yield break; - } - - foreach (var path in _safeIOReadFilePaths) - { - yield return path.Key; - } - } - - public IEnumerable GlobalIOWriteWhitelist() - { - using var lck = _safeIOWriteLock.AcquireReaderLock().GetAwaiter().GetResult(); - - if (_safeIOWriteFilePaths.Count == 0) - { - yield break; - } - - foreach (var path in _safeIOWriteFilePaths) - { - yield return path.Key; - } - } - - public bool IOReadWhiteListContains(string filePath) - { - if (filePath.IsNullOrWhiteSpace()) - return false; - return _safeIOReadFilePaths.ContainsKey(filePath); - } - - public bool IOWriteWhiteListContains(string filePath) - { - if (filePath.IsNullOrWhiteSpace()) - return false; - return _safeIOWriteFilePaths.ContainsKey(filePath); - } - - public string LocalDataSavePath => Path.Combine(ExecutionLocation, "/Data/Mods/"); - + public string LocalDataSavePath => Path.Combine(ExecutionLocation, "Data/Mods").CleanUpPathCrossPlatform(); public string LocalDataPathRegex => "%ModDir%"; - public string RunLocation => ExecutionLocation; - public bool GlobalSafeIOEnabled => false; - public string LocalPackageDataPath - { - get - { - return ContainsIllegalPaths(LocalDataSavePath) ? $"/Data/Mods/{LocalDataPathRegex}" - : Path.Combine(LocalDataSavePath, LocalDataPathRegex); - - bool ContainsIllegalPaths(string path) - { - throw new NotImplementedException(); - } - } - } - - - public FluentResults.Result SetSafeReadFilePaths(string[] filePaths) - { - using var lck = _safeIOReadLock.AcquireWriterLock().GetAwaiter().GetResult(); - return SetSafeDirectory(_safeIOReadFilePaths, filePaths); - } - - public FluentResults.Result SetSafeWriteFilePaths(string[] filePaths) - { - using var lck = _safeIOWriteLock.AcquireWriterLock().GetAwaiter().GetResult(); - return SetSafeDirectory(_safeIOWriteFilePaths, filePaths); - } - - private FluentResults.Result SetSafeDirectory(ConcurrentDictionary target, string[] filePaths) - { - if (filePaths is null || filePaths.Length < 1) - { - target.Clear(); - return FluentResults.Result.Ok(); - } - - FluentResults.Result result = new(); - - target.Clear(); - foreach (string path in filePaths) - { - if (path.IsNullOrWhiteSpace()) - { - result = result.WithError($"ServicesConfigData: A supplied whitelist path was null."); - continue; - } - - try - { - var path2 = Path.GetFullPath(path); - target.TryAdd(path2, 0); - } - catch (Exception e) - { - result = result.WithError( - new ExceptionalError(e).WithMetadata(FluentResults.LuaCs.MetadataType.ExceptionObject, this)); - continue; - } - } - - return result.WithSuccess($"Whitelist updated."); - } + public string LocalPackageDataPath => Path.Combine(LocalDataSavePath, LocalDataPathRegex); public void Dispose() { diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs index 226f2c6e1..5a0f6a09b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs @@ -326,7 +326,9 @@ namespace Barotrauma registrationProvider.RegisterTypeProviders(ConfigService, null); } Logger.LogResults(PackageManagementService.LoadPackagesInfo(ContentPackageManager.EnabledPackages.All.ToImmutableArray())); + Logger.LogResults(ConfigService.LoadSavedConfigsValues()); LoadLuaCsConfig(); + } CurrentRunState = RunState.LoadedNoExec; diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ConfigService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ConfigService.cs index 2cfd7a265..445da3fc0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ConfigService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ConfigService.cs @@ -112,13 +112,14 @@ public sealed partial class ConfigService : IConfigService _settingsInstances.Clear(); _instanceFactory.Clear(); _settingsInstancesByPackage.Clear(); + _storageService.PurgeCache(); return result; } #endregion - private const string SaveDataFileName = "SettingData.xml"; + private const string SaveDataFileName = "SettingsData.xml"; private readonly ConcurrentDictionary<(ContentPackage OwnerPackage, string InternalName), ISettingBase> _settingsInstances = new(); @@ -294,7 +295,21 @@ public sealed partial class ConfigService : IConfigService public FluentResults.Result LoadSavedConfigsValues() { - throw new NotImplementedException(); + ImmutableArray cfgValues; + using (var lck = _operationLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult()) + { + IService.CheckDisposed(this); + cfgValues = _settingsInstances.Select(kvp => kvp.Value).ToImmutableArray(); + } + + var ret = new FluentResults.Result(); + + foreach (var settingBase in cfgValues) + { + ret.WithReasons(LoadSavedValueForConfig(settingBase).Reasons); + } + + return ret; } public FluentResults.Result SaveConfigValue(ISettingBase setting) @@ -331,6 +346,10 @@ public sealed partial class ConfigService : IConfigService var attr = new XAttribute("Value", str); currentTarget.Add(attr); } + else + { + tgt.Value = str; + } return FluentResults.Result.Ok(); }, diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LoggerService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LoggerService.cs index ec455ae0a..f7488e925 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LoggerService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/LoggerService.cs @@ -195,7 +195,6 @@ public partial class LoggerService : ILoggerService LogError($"FluentResults::IError: {error.Message}"); } - if (error.Reasons != null) { foreach (var reason in error.Reasons) @@ -209,17 +208,17 @@ public partial class LoggerService : ILoggerService public void LogDebug(string message, Color? color = null) { - throw new NotImplementedException(); + throw new NotImplementedException($"@EvilFactory will implement this at the end of development."); } public void LogDebugWarning(string message) { - throw new NotImplementedException(); + throw new NotImplementedException($"@EvilFactory will implement this at the end of development."); } public void LogDebugError(string message) { - throw new NotImplementedException(); + throw new NotImplementedException($"@EvilFactory will implement this at the end of development."); } public void Dispose() { } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/StorageService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/StorageService.cs index 0de6b864b..1d3e43ce5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/StorageService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/StorageService.cs @@ -128,10 +128,9 @@ public class StorageService : IStorageService try { var path = System.IO.Path.GetFullPath(Path.Combine( - ConfigData.LocalPackageDataPath.Replace(ConfigData.LocalDataPathRegex, package.ToIdentifier().Value) - .CleanUpPathCrossPlatform(), - localFilePath)); - if (!path.StartsWith(ConfigData.LocalDataSavePath)) + ConfigData.LocalPackageDataPath.Replace(ConfigData.LocalDataPathRegex, package.Name).CleanUpPathCrossPlatform(), + localFilePath.CleanUpPathCrossPlatform())); + if (!path.StartsWith(Path.GetFullPath(ConfigData.LocalDataSavePath))) ThrowHelper.ThrowUnauthorizedAccessException($"{nameof(GetAbsolutePathForLocal)}: The local path of '{path}' is not a local path!"); return path; } @@ -433,7 +432,8 @@ public class StorageService : IStorageService { var fp = filePath.CleanUpPath(); fp = System.IO.Path.IsPathRooted(fp) ? fp : System.IO.Path.GetFullPath(fp); - System.IO.File.WriteAllText(fp, t, encoding); + Directory.CreateDirectory(Path.GetDirectoryName(fp)!); + System.IO.File.WriteAllText(fp, t, encoding ?? Encoding.UTF8); if (UseCaching) _fsCache[filePath] = t; return new FluentResults.Result().WithSuccess($"Saved to file successfully"); @@ -460,6 +460,7 @@ public class StorageService : IStorageService { var fp = filePath.CleanUpPath(); fp = System.IO.Path.IsPathRooted(fp) ? fp : System.IO.Path.GetFullPath(fp); + Directory.CreateDirectory(Path.GetDirectoryName(fp)!); System.IO.File.WriteAllBytes(fp, b); if (UseCaching) _fsCache[filePath] = b;