mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
This is intended for content-side settings menus, so we can show users a "does this look correct" prompt after changing sensitive settings like graphics or UI, without risking an untimely config save *storing* broken CVar config.
280 lines
8.5 KiB
C#
280 lines
8.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using Robust.Shared.Console;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Localization;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Robust.Shared.Configuration
|
|
{
|
|
public static class CVarCommandUtil
|
|
{
|
|
/// <summary>
|
|
/// Parses a string into an object of the given type.
|
|
/// </summary>
|
|
/// <exception cref="FormatException">Thrown if the string could not be parsed into the given type.</exception>
|
|
/// <exception cref="NotSupportedException">Thrown if the type is not supported.</exception>
|
|
public static object ParseObject(Type type, string input)
|
|
{
|
|
if (type == typeof(bool))
|
|
{
|
|
if (bool.TryParse(input, out var val))
|
|
return val;
|
|
|
|
if (Parse.TryInt32(input, out var intVal))
|
|
{
|
|
if (intVal == 0) return false;
|
|
if (intVal == 1) return true;
|
|
}
|
|
|
|
throw new FormatException($"Could not parse bool value: {input}");
|
|
}
|
|
|
|
if (type == typeof(string))
|
|
{
|
|
return input;
|
|
}
|
|
|
|
if (type == typeof(int))
|
|
{
|
|
return Parse.Int32(input);
|
|
}
|
|
|
|
if (type == typeof(float))
|
|
{
|
|
return Parse.Float(input);
|
|
}
|
|
|
|
if (type == typeof(long))
|
|
{
|
|
return long.Parse(input);
|
|
}
|
|
|
|
if (type == typeof(ushort))
|
|
{
|
|
return ushort.Parse(input);
|
|
}
|
|
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
internal static IEnumerable<CompletionOption> GetCVarCompletionOptions(IConfigurationManager cfg)
|
|
{
|
|
return cfg.GetRegisteredCVars()
|
|
.Select(c => new CompletionOption(c, GetCVarValueHint(cfg, c)));
|
|
}
|
|
|
|
private static string GetCVarValueHint(IConfigurationManager cfg, string cVar)
|
|
{
|
|
var flags = cfg.GetCVarFlags(cVar);
|
|
if ((flags & CVar.CONFIDENTIAL) != 0)
|
|
return Loc.GetString("cmd-cvar-value-hidden");
|
|
|
|
var value = cfg.GetCVar<object>(cVar).ToString() ?? "";
|
|
if (value.Length > 50)
|
|
value = $"{value[..51]}…";
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
|
internal sealed class CVarCommand : LocalizedCommands
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
|
|
|
public override string Command => "cvar";
|
|
|
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length is < 1 or > 2)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar-invalid-args"));
|
|
return;
|
|
}
|
|
|
|
var name = args[0];
|
|
|
|
if (name == "?")
|
|
{
|
|
var cvars = _cfg.GetRegisteredCVars().OrderBy(c => c);
|
|
shell.WriteLine(string.Join("\n", cvars));
|
|
return;
|
|
}
|
|
|
|
if (!_cfg.IsCVarRegistered(name))
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar-not-registered", ("cvar", name)));
|
|
return;
|
|
}
|
|
|
|
if (args.Length == 1)
|
|
{
|
|
// Read CVar
|
|
var value = _cfg.GetCVar<object>(name);
|
|
shell.WriteLine(value.ToString()!);
|
|
}
|
|
else
|
|
{
|
|
// Write CVar
|
|
var value = args[1];
|
|
var type = _cfg.GetCVarType(name);
|
|
try
|
|
{
|
|
var parsed = CVarCommandUtil.ParseObject(type, value);
|
|
_cfg.SetCVar(name, parsed);
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar-parse-error", ("type", type)));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
var helpQuestion = Loc.GetString("cmd-cvar-compl-list");
|
|
|
|
return CompletionResult.FromHintOptions(
|
|
CVarCommandUtil.GetCVarCompletionOptions(_cfg)
|
|
.Union(new[] { new CompletionOption("?", helpQuestion) })
|
|
.OrderBy(c => c.Value),
|
|
Loc.GetString("cmd-cvar-arg-name"));
|
|
}
|
|
|
|
var cvar = args[0];
|
|
if (!_cfg.IsCVarRegistered(cvar))
|
|
return CompletionResult.Empty;
|
|
|
|
var type = _cfg.GetCVarType(cvar);
|
|
return CompletionResult.FromHint($"<{type.Name}>");
|
|
}
|
|
}
|
|
|
|
internal sealed class CVarSubsCommand : LocalizedCommands
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
|
|
|
public override string Command => "cvar_subs";
|
|
|
|
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length < 1)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-cvar_subs-invalid-args"));
|
|
return;
|
|
}
|
|
|
|
var name = args[0];
|
|
var subs = ((ConfigurationManager)_cfg).GetSubs(name);
|
|
|
|
foreach (var @delegate in subs)
|
|
{
|
|
shell.WriteLine(ShowDelegateInfo(@delegate));
|
|
}
|
|
}
|
|
|
|
private static string ShowDelegateInfo(Delegate del)
|
|
{
|
|
return $"{del}: {del.Method} -> {del.Target}";
|
|
}
|
|
|
|
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
return CompletionResult.FromHintOptions(
|
|
_cfg.GetRegisteredCVars()
|
|
.Select(c => new CompletionOption(c))
|
|
.OrderBy(c => c.Value),
|
|
Loc.GetString("cmd-cvar_subs-arg-name"));
|
|
}
|
|
|
|
return CompletionResult.Empty;
|
|
}
|
|
}
|
|
|
|
internal sealed class ConfigMarkRollbackCommand : IConsoleCommand
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfg = null!;
|
|
|
|
public string Command => "config_rollback_mark";
|
|
public string Description => "";
|
|
public string Help => "";
|
|
|
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length is < 1 or > 2)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-invalid-arg-number-error"));
|
|
return;
|
|
}
|
|
|
|
_cfg.MarkForRollback(args[0]);
|
|
}
|
|
|
|
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
return CompletionResult.FromOptions(
|
|
CVarCommandUtil.GetCVarCompletionOptions(_cfg)
|
|
.OrderBy(c => c.Value));
|
|
}
|
|
|
|
return CompletionResult.Empty;
|
|
}
|
|
}
|
|
|
|
internal sealed class ConfigUnmarkRollbackCommand : IConsoleCommand
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfg = null!;
|
|
|
|
public string Command => "config_rollback_unmark";
|
|
public string Description => "";
|
|
public string Help => "";
|
|
|
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
if (args.Length is < 1 or > 2)
|
|
{
|
|
shell.WriteError(Loc.GetString("cmd-invalid-arg-number-error"));
|
|
return;
|
|
}
|
|
|
|
_cfg.UnmarkForRollback(args[0]);
|
|
}
|
|
|
|
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
|
{
|
|
if (args.Length == 1)
|
|
{
|
|
return CompletionResult.FromOptions(
|
|
CVarCommandUtil.GetCVarCompletionOptions(_cfg)
|
|
.OrderBy(c => c.Value));
|
|
}
|
|
|
|
return CompletionResult.Empty;
|
|
}
|
|
}
|
|
|
|
|
|
internal sealed class ConfigApplyRollbackCommand : IConsoleCommand
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfg = null!;
|
|
|
|
public string Command => "config_rollback_apply";
|
|
public string Description => "";
|
|
public string Help => "";
|
|
|
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
{
|
|
_cfg.ApplyRollback();
|
|
}
|
|
}
|
|
}
|