- Loading/Saving for Settings via console.

This commit is contained in:
Maplewheels
2026-02-08 20:23:30 -05:00
parent bcc4357a16
commit a505d48a4c
6 changed files with 40 additions and 146 deletions
@@ -2385,6 +2385,10 @@ namespace Barotrauma
if (setting.TrySetValue(valueString)) if (setting.TrySetValue(valueString))
{ {
NewMessage($"Set config {internalName} value to {valueString}", Color.Green); 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 else
{ {
@@ -25,31 +25,14 @@ public interface IStorageServiceConfig : IService
#if CLIENT #if CLIENT
string TempDownloadsDirectory { get; } string TempDownloadsDirectory { get; }
#endif #endif
//ReadOnlyCollection<string> SafeIOReadDirectories { get; }
//ReadOnlyCollection<string> SafeIOWriteDirectories { get; }
IEnumerable<string> GlobalIOReadWhitelist();
IEnumerable<string> GlobalIOWriteWhitelist();
bool IOReadWhiteListContains(string filePath);
bool IOWriteWhiteListContains(string filePath);
string LocalDataSavePath { get; } string LocalDataSavePath { get; }
string LocalDataPathRegex { get; } string LocalDataPathRegex { get; }
string LocalPackageDataPath { get; } string LocalPackageDataPath { get; }
public string RunLocation { get; }
bool GlobalSafeIOEnabled { get; }
} }
internal interface IStorageServiceConfigUpdate public record StorageServiceConfig : IStorageServiceConfig
{ {
public FluentResults.Result SetSafeReadFilePaths(string[] filePaths); private static readonly string ExecutionLocation = Directory.GetCurrentDirectory().CleanUpPathCrossPlatform();
public FluentResults.Result SetSafeWriteFilePaths(string[] filePaths);
}
public record StorageServiceConfig : IStorageServiceConfig, IStorageServiceConfigUpdate
{
private static readonly string ExecutionLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.CleanUpPath());
public string LocalModsDirectory { get; init; } = System.IO.Path.GetFullPath(ContentPackage.LocalModsDir).CleanUpPath(); public string LocalModsDirectory { get; init; } = System.IO.Path.GetFullPath(ContentPackage.LocalModsDir).CleanUpPath();
public string WorkshopModsDirectory { get; init; } = System.IO.Path.GetFullPath(ContentPackage.WorkshopModsDir).CleanUpPath(); public string WorkshopModsDirectory { get; init; } = System.IO.Path.GetFullPath(ContentPackage.WorkshopModsDir).CleanUpPath();
@@ -60,125 +43,11 @@ public record StorageServiceConfig : IStorageServiceConfig, IStorageServiceConfi
#if CLIENT #if CLIENT
public string TempDownloadsDirectory { get; init; } = System.IO.Path.GetFullPath(ModReceiver.DownloadFolder).CleanUpPath(); public string TempDownloadsDirectory { get; init; } = System.IO.Path.GetFullPath(ModReceiver.DownloadFolder).CleanUpPath();
#endif #endif
public string LocalDataSavePath => Path.Combine(ExecutionLocation, "Data/Mods").CleanUpPathCrossPlatform();
private readonly AsyncReaderWriterLock _safeIOReadLock = new();
private readonly AsyncReaderWriterLock _safeIOWriteLock = new();
private readonly ConcurrentDictionary<string,byte> _safeIOReadFilePaths = new();
private readonly ConcurrentDictionary<string,byte> _safeIOWriteFilePaths = new();
public IEnumerable<string> 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<string> 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 LocalDataPathRegex => "%ModDir%"; public string LocalDataPathRegex => "%ModDir%";
public string RunLocation => ExecutionLocation; public string RunLocation => ExecutionLocation;
public bool GlobalSafeIOEnabled => false;
public string LocalPackageDataPath public string LocalPackageDataPath => Path.Combine(LocalDataSavePath, LocalDataPathRegex);
{
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<string,byte> 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 void Dispose() public void Dispose()
{ {
@@ -326,7 +326,9 @@ namespace Barotrauma
registrationProvider.RegisterTypeProviders(ConfigService, null); registrationProvider.RegisterTypeProviders(ConfigService, null);
} }
Logger.LogResults(PackageManagementService.LoadPackagesInfo(ContentPackageManager.EnabledPackages.All.ToImmutableArray())); Logger.LogResults(PackageManagementService.LoadPackagesInfo(ContentPackageManager.EnabledPackages.All.ToImmutableArray()));
Logger.LogResults(ConfigService.LoadSavedConfigsValues());
LoadLuaCsConfig(); LoadLuaCsConfig();
} }
CurrentRunState = RunState.LoadedNoExec; CurrentRunState = RunState.LoadedNoExec;
@@ -112,13 +112,14 @@ public sealed partial class ConfigService : IConfigService
_settingsInstances.Clear(); _settingsInstances.Clear();
_instanceFactory.Clear(); _instanceFactory.Clear();
_settingsInstancesByPackage.Clear(); _settingsInstancesByPackage.Clear();
_storageService.PurgeCache();
return result; return result;
} }
#endregion #endregion
private const string SaveDataFileName = "SettingData.xml"; private const string SaveDataFileName = "SettingsData.xml";
private readonly ConcurrentDictionary<(ContentPackage OwnerPackage, string InternalName), ISettingBase> private readonly ConcurrentDictionary<(ContentPackage OwnerPackage, string InternalName), ISettingBase>
_settingsInstances = new(); _settingsInstances = new();
@@ -294,7 +295,21 @@ public sealed partial class ConfigService : IConfigService
public FluentResults.Result LoadSavedConfigsValues() public FluentResults.Result LoadSavedConfigsValues()
{ {
throw new NotImplementedException(); ImmutableArray<ISettingBase> 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) public FluentResults.Result SaveConfigValue(ISettingBase setting)
@@ -331,6 +346,10 @@ public sealed partial class ConfigService : IConfigService
var attr = new XAttribute("Value", str); var attr = new XAttribute("Value", str);
currentTarget.Add(attr); currentTarget.Add(attr);
} }
else
{
tgt.Value = str;
}
return FluentResults.Result.Ok(); return FluentResults.Result.Ok();
}, },
@@ -195,7 +195,6 @@ public partial class LoggerService : ILoggerService
LogError($"FluentResults::IError: {error.Message}"); LogError($"FluentResults::IError: {error.Message}");
} }
if (error.Reasons != null) if (error.Reasons != null)
{ {
foreach (var reason in error.Reasons) foreach (var reason in error.Reasons)
@@ -209,17 +208,17 @@ public partial class LoggerService : ILoggerService
public void LogDebug(string message, Color? color = null) 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) 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) public void LogDebugError(string message)
{ {
throw new NotImplementedException(); throw new NotImplementedException($"@EvilFactory will implement this at the end of development.");
} }
public void Dispose() { } public void Dispose() { }
@@ -128,10 +128,9 @@ public class StorageService : IStorageService
try try
{ {
var path = System.IO.Path.GetFullPath(Path.Combine( var path = System.IO.Path.GetFullPath(Path.Combine(
ConfigData.LocalPackageDataPath.Replace(ConfigData.LocalDataPathRegex, package.ToIdentifier().Value) ConfigData.LocalPackageDataPath.Replace(ConfigData.LocalDataPathRegex, package.Name).CleanUpPathCrossPlatform(),
.CleanUpPathCrossPlatform(), localFilePath.CleanUpPathCrossPlatform()));
localFilePath)); if (!path.StartsWith(Path.GetFullPath(ConfigData.LocalDataSavePath)))
if (!path.StartsWith(ConfigData.LocalDataSavePath))
ThrowHelper.ThrowUnauthorizedAccessException($"{nameof(GetAbsolutePathForLocal)}: The local path of '{path}' is not a local path!"); ThrowHelper.ThrowUnauthorizedAccessException($"{nameof(GetAbsolutePathForLocal)}: The local path of '{path}' is not a local path!");
return path; return path;
} }
@@ -433,7 +432,8 @@ public class StorageService : IStorageService
{ {
var fp = filePath.CleanUpPath(); var fp = filePath.CleanUpPath();
fp = System.IO.Path.IsPathRooted(fp) ? fp : System.IO.Path.GetFullPath(fp); 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) if (UseCaching)
_fsCache[filePath] = t; _fsCache[filePath] = t;
return new FluentResults.Result().WithSuccess($"Saved to file successfully"); return new FluentResults.Result().WithSuccess($"Saved to file successfully");
@@ -460,6 +460,7 @@ public class StorageService : IStorageService
{ {
var fp = filePath.CleanUpPath(); var fp = filePath.CleanUpPath();
fp = System.IO.Path.IsPathRooted(fp) ? fp : System.IO.Path.GetFullPath(fp); fp = System.IO.Path.IsPathRooted(fp) ? fp : System.IO.Path.GetFullPath(fp);
Directory.CreateDirectory(Path.GetDirectoryName(fp)!);
System.IO.File.WriteAllBytes(fp, b); System.IO.File.WriteAllBytes(fp, b);
if (UseCaching) if (UseCaching)
_fsCache[filePath] = b; _fsCache[filePath] = b;