using System.Globalization; namespace FakeGameServer; internal enum FakeMode { Normal, NoReady, FailOnStart, CrashAfterReady, IgnoreStop, IgnoreAll, } internal sealed record FakeSettings( FakeMode Mode, int StartupMs, int StopMs, int CrashAfterMs, int CrashExitCode, bool StdinEofStopsServer) { public static FakeSettings FromEnvironment() { var mode = Enum.TryParse(Env("FAKE_MODE"), true, out var parsed) ? parsed : FakeMode.Normal; return new FakeSettings( mode, EnvInt("FAKE_STARTUP_MS", 500), EnvInt("FAKE_STOP_MS", 200), EnvInt("FAKE_CRASH_AFTER_MS", 300), EnvInt("FAKE_CRASH_EXIT_CODE", 0), string.Equals(Env("FAKE_STDIN_EOF"), "stop", StringComparison.OrdinalIgnoreCase)); } private static string? Env(string name) => Environment.GetEnvironmentVariable(name); private static int EnvInt(string name, int fallback) => int.TryParse(Env(name), NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? value : fallback; } internal sealed record CommandLine(string? DataPath, int? Port, string? SetConfig) { // Flags that take a value. Like the real game, the next token is taken as the value // when there is no "=", even if that token is another flag. private static readonly HashSet ValueOptions = new(StringComparer.OrdinalIgnoreCase) { "dataPath", "port", "setconfig", "withconfig", "logPath", "ip", "maxclients", }; public static CommandLine Parse(string[] args) { var values = new Dictionary(StringComparer.OrdinalIgnoreCase); for (var i = 0; i < args.Length; i++) { var arg = args[i]; if (!arg.StartsWith("--", StringComparison.Ordinal)) { continue; } var body = arg[2..]; var eq = body.IndexOf('=', StringComparison.Ordinal); if (eq >= 0) { values[body[..eq]] = body[(eq + 1)..]; } else if (ValueOptions.Contains(body) && i + 1 < args.Length) { values[body] = args[++i]; } else { values[body] = null; } } values.TryGetValue("dataPath", out var dataPath); values.TryGetValue("setconfig", out var setConfig); values.TryGetValue("port", out var portText); int? port = int.TryParse(portText, NumberStyles.None, CultureInfo.InvariantCulture, out var n) ? n : null; return new CommandLine(dataPath, port, setConfig); } }