LoadDefaultsFromTomlStream to load CVars as CVar default overrides.

This commit is contained in:
Pieter-Jan Briers
2022-12-01 22:40:19 +01:00
parent cb29e6e19d
commit 86ffed9afb
3 changed files with 86 additions and 55 deletions

View File

@@ -45,6 +45,7 @@ END TEMPLATE-->
* See also [the HTTP API documentation](https://docs.spacestation14.io/en/engine/http-api) for reference.
* `GameShared` now has a `Dependencies` property to allow access to the game's `IDependencyCollection`. This makes it possible to avoid using static `IoCManager` in `EntryPoint`-type content code.
* A new define constant `DEVELOPMENT` has been defined, equivalent to `!FULL_RELEASE`. See [the docs](https://docs.spacestation14.io/en/technical-docs/preprocessor-defines) for details.
* New `IConfigurationManager.LoadDefaultsFromTomlStream` to load a TOML file as CVar default overrides.
### Bugfixes

View File

@@ -55,14 +55,16 @@ namespace Robust.Shared.Configuration
var loaded = new HashSet<string>();
try
{
var tblRoot = Toml.ReadStream(file);
var callbackEvents = new ValueList<ValueChangedInvoke>();
// Ensure callbacks are raised OUTSIDE the write lock.
using (Lock.WriteGuard())
{
ProcessTomlObject(tblRoot, ref callbackEvents, loaded);
foreach (var (cvar, value) in ParseCVarValuesFromToml(file))
{
loaded.Add(cvar);
LoadTomlVar(cvar, value, ref callbackEvents);
}
}
foreach (var callback in callbackEvents)
@@ -79,6 +81,42 @@ namespace Robust.Shared.Configuration
return loaded;
}
private void LoadTomlVar(
string cvar,
object value,
ref ValueList<ValueChangedInvoke> changedInvokes)
{
if (_configVars.TryGetValue(cvar, out var cfgVar))
{
// overwrite the value with the saved one
cfgVar.Value = value;
if (SetupInvokeValueChanged(cfgVar, value) is { } invoke)
changedInvokes.Add(invoke);
}
else
{
//or add another unregistered CVar
//Note: the defaultValue is arbitrarily 0, it will get overwritten when the cvar is registered.
cfgVar = new ConfigVar(cvar, 0, CVar.NONE) { Value = value };
_configVars.Add(cvar, cfgVar);
}
cfgVar.ConfigModified = true;
}
public HashSet<string> LoadDefaultsFromTomlStream(Stream stream)
{
var loaded = new HashSet<string>();
foreach (var (cvar, value) in ParseCVarValuesFromToml(stream))
{
loaded.Add(cvar);
OverrideDefault(cvar, value);
}
return loaded;
}
/// <inheritdoc />
public HashSet<string> LoadFromFile(string configFile)
{
@@ -102,57 +140,6 @@ namespace Robust.Shared.Configuration
_configFile = configFile;
}
/// <summary>
/// A recursive function that walks over the config tree, transforming all key nodes into CVars.
/// </summary>
/// <param name="obj">The root table of the TOML document.</param>
/// <param name="changedInvokes">List of CVars that will need to have their InvokeValueChanged ran.</param>
/// <param name="tablePath">For internal use only, the current path to the node.</param>
private void ProcessTomlObject(
TomlObject obj,
ref ValueList<ValueChangedInvoke> changedInvokes,
HashSet<string> loadedCvars,
string tablePath = "")
{
if (obj is TomlTable table) // this is a table
{
foreach (var kvTml in table)
{
string newPath;
if ((kvTml.Value is TomlTable))
newPath = tablePath + kvTml.Key + TABLE_DELIMITER;
else
newPath = tablePath + kvTml.Key;
ProcessTomlObject(kvTml.Value, ref changedInvokes, loadedCvars, newPath);
}
}
else // this is a key, add CVar
{
// if the CVar has already been registered
var tomlValue = TypeConvert(obj);
if (_configVars.TryGetValue(tablePath, out var cfgVar))
{
// overwrite the value with the saved one
cfgVar.Value = tomlValue;
loadedCvars.Add(cfgVar.Name);
if (SetupInvokeValueChanged(cfgVar, tomlValue) is { } invoke)
changedInvokes.Add(invoke);
}
else
{
//or add another unregistered CVar
//Note: the defaultValue is arbitrarily 0, it will get overwritten when the cvar is registered.
cfgVar = new ConfigVar(tablePath, 0, CVar.NONE) { Value = tomlValue };
_configVars.Add(tablePath, cfgVar);
loadedCvars.Add(cfgVar.Name);
}
cfgVar.ConfigModified = true;
}
}
/// <inheritdoc />
public void SaveToTomlStream(Stream stream, IEnumerable<string> cvars)
{
@@ -244,7 +231,8 @@ namespace Robust.Shared.Configuration
// Don't write if Archive flag is not set.
// Don't write if the cVar is the default value.
var cvars = _configVars.Where(x => x.Value.ConfigModified
|| ((x.Value.Flags & CVar.ARCHIVE) == 0 && x.Value.Value != null && !x.Value.Value.Equals(x.Value.DefaultValue))).Select(x => x.Key);
|| ((x.Value.Flags & CVar.ARCHIVE) == 0 && x.Value.Value != null &&
!x.Value.Value.Equals(x.Value.DefaultValue))).Select(x => x.Key);
using var file = File.OpenWrite(_configFile);
SaveToTomlStream(file, cvars);
@@ -637,6 +625,39 @@ namespace Robust.Shared.Configuration
};
}
private IEnumerable<(string cvar, object value)> ParseCVarValuesFromToml(Stream stream)
{
var tblRoot = Toml.ReadStream(stream);
return ProcessTomlObject(tblRoot, "");
IEnumerable<(string cvar, object value)> ProcessTomlObject(TomlObject obj, string tablePath)
{
if (obj is TomlTable table)
{
foreach (var kvTml in table)
{
string newPath;
if ((kvTml.Value is TomlTable))
newPath = tablePath + kvTml.Key + TABLE_DELIMITER;
else
newPath = tablePath + kvTml.Key;
foreach (var tuple in ProcessTomlObject(kvTml.Value, newPath))
{
yield return tuple;
}
}
yield break;
}
var tomlValue = TypeConvert(obj);
yield return (tablePath, tomlValue);
}
}
/// <summary>
/// Holds the data for a single configuration variable.
/// </summary>

View File

@@ -52,6 +52,15 @@ namespace Robust.Shared.Configuration
HashSet<string> LoadFromTomlStream(Stream stream);
/// <summary>
/// Load a TOML config file and use the CVar values specified as an <see cref="OverrideDefault"/>.
/// </summary>
/// <remarks>
/// All CVars in the TOML file must be registered when this function is called.
/// </remarks>
/// <returns>A set of all CVars touched.</returns>
HashSet<string> LoadDefaultsFromTomlStream(Stream stream);
/// <summary>
/// Register a CVar with the system. This must be done before the CVar is accessed.
/// </summary>