From a9c9a0de6802e07228e4e090a3794f943a9cb200 Mon Sep 17 00:00:00 2001 From: zznty <94796179+zznty@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:36:25 +0700 Subject: [PATCH] refactor restart and config handling --- Torch.Server/TorchConfig.cs | 211 ++++++++++++++---------------------- Torch.Server/TorchServer.cs | 28 +++-- Torch/CommandLine.cs | 138 ----------------------- 3 files changed, 100 insertions(+), 277 deletions(-) delete mode 100644 Torch/CommandLine.cs diff --git a/Torch.Server/TorchConfig.cs b/Torch.Server/TorchConfig.cs index 6eb644f..397d7c9 100644 --- a/Torch.Server/TorchConfig.cs +++ b/Torch.Server/TorchConfig.cs @@ -1,167 +1,114 @@ using System; using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Runtime.CompilerServices; using System.Xml.Serialization; -using NLog; using Torch.API; using Torch.Views; -namespace Torch.Server +namespace Torch.Server; + +public class TorchConfig : ViewModel, ITorchConfig { - // TODO: redesign this gerbage - public class TorchConfig : CommandLine, ITorchConfig, INotifyPropertyChanged - { - private static Logger _log = LogManager.GetLogger("Config"); + public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate; + public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate; - public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate; - public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate; - - private bool _autostart; - private bool _restartOnCrash; - private bool _noGui; - private bool _getPluginUpdates = true; - private bool _getTorchUpdates = true; - private int _tickTimeout = 60; - private bool _localPlugins; - private bool _disconnectOnRestart; - private string _chatName = "Server"; - private string _chatColor = "Red"; - private bool _enableWhitelist = false; - private List _whitelist = new List(); - private int _windowWidth = 980; - private int _windowHeight = 588; - private bool _independentConsole = false; - private bool _enableAsserts = false; - private int _fontSize = 16; - private UGCServiceType _ugcServiceType = UGCServiceType.Steam; - private bool _entityManagerEnabled = true; + /// + [XmlIgnore] + public bool NoUpdate { get; set; } - /// - [XmlIgnore, Arg("noupdate", "Disable automatically downloading game and plugin updates.")] - public bool NoUpdate { get; set; } + /// + [XmlIgnore] + public bool ForceUpdate { get; set; } - /// - [XmlIgnore, Arg("forceupdate", "Manually check for and install updates.")] - public bool ForceUpdate { get; set; } + /// + /// Permanent flag to ALWAYS automatically start the server + /// + [Display(Name = "Auto Start", Description = "Permanent flag to ALWAYS automatically start the server.", GroupName = "Server")] + public bool Autostart { get; set; } - /// - /// Permanent flag to ALWAYS automatically start the server - /// - [Display(Name = "Auto Start", Description = "Permanent flag to ALWAYS automatically start the server.", GroupName = "Server")] - public bool Autostart { get => _autostart; set => Set(value, ref _autostart); } + /// + /// Temporary flag to automatically start the server only on the next run + /// + [XmlIgnore] + public bool TempAutostart { get; set; } - /// - /// Temporary flag to automatically start the server only on the next run - /// - [Arg("autostart", "Start the server immediately.")] - [XmlIgnore] - public bool TempAutostart { get; set; } + /// + [Display(Name = "Restart On Crash", Description = "Automatically restart the server if it crashes.", GroupName = "Server")] + public bool RestartOnCrash { get; set; } - /// - [Arg("restartoncrash", "Automatically restart the server if it crashes.")] - [Display(Name = "Restart On Crash", Description = "Automatically restart the server if it crashes.", GroupName = "Server")] - public bool RestartOnCrash { get => _restartOnCrash; set => Set(value, ref _restartOnCrash); } + public string InstancePath { get; set; } - public string InstancePath { get; set; } + /// + [Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")] + public bool NoGui { get; set; } - /// - [Arg("nogui", "Do not show the Torch UI.")] - [Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")] - public bool NoGui { get => _noGui; set => Set(value, ref _noGui); } + /// + [Display(Name = "Update Torch", Description = "Check every start for new versions of torch.", + GroupName = "Server")] + public bool GetTorchUpdates { get; set; } = true; - /// - [Display(Name = "Update Torch", Description = "Check every start for new versions of torch.", GroupName = "Server")] - public bool GetTorchUpdates { get => _getTorchUpdates; set => Set(value, ref _getTorchUpdates); } + public string InstanceName { get; set; } - public string InstanceName { get; set; } + /// + [Display(Name = "Update Plugins", Description = "Check every start for new versions of plugins.", + GroupName = "Server")] + public bool GetPluginUpdates { get; set; } = true; - /// - [Display(Name = "Update Plugins", Description = "Check every start for new versions of plugins.", GroupName = "Server")] - public bool GetPluginUpdates { get => _getPluginUpdates; set => Set(value, ref _getPluginUpdates); } + /// + [Display(Name = "Watchdog Timeout", Description = "Watchdog timeout (in seconds).", GroupName = "Server")] + public int TickTimeout { get; set; } = 60; - /// - [Display(Name = "Watchdog Timeout", Description = "Watchdog timeout (in seconds).", GroupName = "Server")] - public int TickTimeout { get => _tickTimeout; set => Set(value, ref _tickTimeout); } + /// + public List Plugins { get; set; } = new(); - /// - [Arg("plugins", "Starts Torch with the given plugin GUIDs (space delimited).")] - public List Plugins { get; set; } = new List(); + [Display(Name = "Local Plugins", Description = "Loads all pluhins from disk, ignores the plugins defined in config.", GroupName = "In-Game")] + public bool LocalPlugins { get; set; } - [Arg("localplugins", "Loads all pluhins from disk, ignores the plugins defined in config.")] - [Display(Name = "Local Plugins", Description = "Loads all pluhins from disk, ignores the plugins defined in config.", GroupName = "In-Game")] - public bool LocalPlugins { get => _localPlugins; set => Set(value, ref _localPlugins); } + [Display(Name = "Auto Disconnect", Description = "When server restarts, all clients are rejected to main menu to prevent auto rejoin.", GroupName = "In-Game")] + public bool DisconnectOnRestart { get; set; } - [Arg("disconnect", "When server restarts, all clients are rejected to main menu to prevent auto rejoin.")] - [Display(Name = "Auto Disconnect", Description = "When server restarts, all clients are rejected to main menu to prevent auto rejoin.", GroupName = "In-Game")] - public bool DisconnectOnRestart { get => _disconnectOnRestart; set => Set(value, ref _disconnectOnRestart); } + [Display(Name = "Chat Name", Description = "Default name for chat from gui, broadcasts etc..", + GroupName = "In-Game")] + public string ChatName { get; set; } = "Server"; - [Display(Name = "Chat Name", Description = "Default name for chat from gui, broadcasts etc..", GroupName = "In-Game")] - public string ChatName { get => _chatName; set => Set(value, ref _chatName); } + [Display(Name = "Chat Color", + Description = "Default color for chat from gui, broadcasts etc.. (Red, Blue, White, Green)", + GroupName = "In-Game")] + public string ChatColor { get; set; } = "Red"; - [Display(Name = "Chat Color", Description = "Default color for chat from gui, broadcasts etc.. (Red, Blue, White, Green)", GroupName = "In-Game")] - public string ChatColor { get => _chatColor; set => Set(value, ref _chatColor); } + [Display(Name = "Enable Whitelist", Description = "Enable Whitelist to prevent random players join while maintance, tests or other.", GroupName = "In-Game")] + public bool EnableWhitelist { get; set; } - [Display(Name = "Enable Whitelist", Description = "Enable Whitelist to prevent random players join while maintance, tests or other.", GroupName = "In-Game")] - public bool EnableWhitelist { get => _enableWhitelist; set => Set(value, ref _enableWhitelist); } + [Display(Name = "Whitelist", Description = "Collection of whitelisted steam ids.", GroupName = "In-Game")] + public List Whitelist { get; set; } = new(); - [Display(Name = "Whitelist", Description = "Collection of whitelisted steam ids.", GroupName = "In-Game")] - public List Whitelist { get => _whitelist; set => Set(value, ref _whitelist); } + [Display(Name = "Width", Description = "Default window width.", GroupName = "Window")] + public int WindowWidth { get; set; } = 980; - [Display(Name = "Width", Description = "Default window width.", GroupName = "Window")] - public int WindowWidth { get => _windowWidth; set => Set(value, ref _windowWidth); } + [Display(Name = "Height", Description = "Default window height", GroupName = "Window")] + public int WindowHeight { get; set; } = 588; - [Display(Name = "Height", Description = "Default window height", GroupName = "Window")] - public int WindowHeight { get => _windowHeight; set => Set(value, ref _windowHeight); } + [Display(Name = "Font Size", Description = "Font size for logging text box. (default is 16)", + GroupName = "Window")] + public int FontSize { get; set; } = 16; - [Display(Name = "Font Size", Description = "Font size for logging text box. (default is 16)", GroupName = "Window")] - public int FontSize { get => _fontSize; set => Set(value, ref _fontSize); } + [Display(Name = "UGC Service Type", Description = "Service for downloading mods", GroupName = "Server")] + public UGCServiceType UgcServiceType { get; set; } = UGCServiceType.Steam; - [Display(Name = "UGC Service Type", Description = "Service for downloading mods", GroupName = "Server")] - public UGCServiceType UgcServiceType - { - get => _ugcServiceType; - set => Set(value, ref _ugcServiceType); - } + public string LastUsedTheme { get; set; } = "Torch Theme"; - public string LastUsedTheme { get; set; } = "Torch Theme"; + [Display(Name = "Independent Console", Description = "Keeps a separate console window open after the main UI loads.", GroupName = "Window")] + public bool IndependentConsole { get; set; } - //Prevent reserved players being written to disk, but allow it to be read - //remove this when ReservedPlayers is removed - private bool ShouldSerializeReservedPlayers() => false; + [XmlIgnore] + public string TestPlugin { get; set; } - [Arg("console", "Keeps a separate console window open after the main UI loads.")] - [Display(Name = "Independent Console", Description = "Keeps a separate console window open after the main UI loads.", GroupName = "Window")] - public bool IndependentConsole { get => _independentConsole; set => Set(value, ref _independentConsole); } + [Display(Name = "Enable Asserts", Description = "Enable Keen's assert logging.", GroupName = "Server")] + public bool EnableAsserts { get; set; } - [XmlIgnore] - [Arg("testplugin", "Path to a plugin to debug. For development use only.")] - public string TestPlugin { get; set; } + [Display(Name = "Enable Entity Manager", Description = "Enable Entity Manager tab. (can affect performance)", + GroupName = "Server")] + public bool EntityManagerEnabled { get; set; } = true; - [Arg("asserts", "Enable Keen's assert logging.")] - [Display(Name = "Enable Asserts", Description = "Enable Keen's assert logging.", GroupName = "Server")] - public bool EnableAsserts { get => _enableAsserts; set => Set(value, ref _enableAsserts); } - - [Display(Name = "Enable Entity Manager", Description = "Enable Entity Manager tab. (can affect performance)", - GroupName = "Server")] - public bool EntityManagerEnabled - { - get => _entityManagerEnabled; - set => Set(value, ref _entityManagerEnabled); - } - - public event PropertyChangedEventHandler PropertyChanged; - - public TorchConfig() { } - - protected void Set(T value, ref T field, [CallerMemberName] string callerName = default) - { - field = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(callerName)); - } - - // for backward compatibility - public void Save(string path = null) => Initializer.Instance?.ConfigPersistent?.Save(path); - } -} + // for backward compatibility + public void Save(string path = null) => Initializer.Instance?.ConfigPersistent?.Save(path); +} \ No newline at end of file diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index 1ad91bf..eebd7df 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -205,16 +205,30 @@ namespace Torch.Server new Thread(() => { StopInternal(); - var config = (TorchConfig)Config; LogManager.Flush(); - - string exe = Assembly.GetExecutingAssembly().Location.Replace("dll", "exe"); - config.TempAutostart = true; - - Process.Start(exe, $"-waitForPid {Environment.ProcessId} {config}"); - +#if DEBUG Environment.Exit(0); +#endif + + var exe = Assembly.GetExecutingAssembly().Location.Replace("dll", "exe"); + + var args = Environment.GetCommandLineArgs(); + + for (var i = 0; i < args.Length; i++) + { + if (args[i].Contains(' ')) + args[i] = $"\"{args[i]}\""; + + if (!args[i].Contains("--tempAutostart", StringComparison.InvariantCultureIgnoreCase) && + !args[i].Contains("--waitForPid", StringComparison.InvariantCultureIgnoreCase)) + continue; + + args[i] = string.Empty; + args[++i] = string.Empty; + } + + Process.Start(exe, $"--waitForPid {Environment.ProcessId} --tempAutostart true {string.Join(" ", args)}"); }) { Name = "Restart thread" diff --git a/Torch/CommandLine.cs b/Torch/CommandLine.cs deleted file mode 100644 index da71001..0000000 --- a/Torch/CommandLine.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using NLog; - -namespace Torch -{ - /// - /// Base class that adds tools for setting type properties through the command line. - /// - public abstract class CommandLine - { - private readonly string _argPrefix; - private readonly Dictionary _args = new Dictionary(); - private readonly Logger _log = LogManager.GetCurrentClassLogger(); - - protected CommandLine(string argPrefix = "-") - { - _argPrefix = argPrefix; - foreach (var prop in GetType().GetProperties()) - { - var attr = prop.GetCustomAttribute(); - if (attr == null) - continue; - _args.Add(attr, prop); - } - } - - public string GetHelp() - { - var sb = new StringBuilder(); - - foreach (var property in _args) - { - var attr = property.Key; - sb.AppendLine($"{_argPrefix}{attr.Name.PadRight(24)}{attr.Description}"); - } - - return sb.ToString(); - } - - public override string ToString() - { - var args = new List(); - foreach (var prop in _args) - { - var attr = prop.Key; - if (prop.Value.PropertyType == typeof(bool) && (bool)prop.Value.GetValue(this)) - { - args.Add($"{_argPrefix}{attr.Name}"); - } - else if (prop.Value.PropertyType == typeof(string)) - { - var str = (string)prop.Value.GetValue(this); - if (string.IsNullOrEmpty(str)) - continue; - args.Add($"{_argPrefix}{attr.Name} \"{str}\""); - } - } - - return string.Join(" ", args); - } - - public bool Parse(string[] args) - { - if (args.Length == 0) - return true; - - if (args[0] == $"{_argPrefix}help") - { - Console.WriteLine(GetHelp()); - return false; - } - - for (var i = 0; i < args.Length; i++) - { - if (!args[i].StartsWith(_argPrefix)) - continue; - - foreach (var property in _args) - { - var argName = property.Key.Name; - if (argName == null) - continue; - - try - { - if (string.Compare(argName, 0, args[i], 1, argName.Length, StringComparison.InvariantCultureIgnoreCase) == 0) - { - if (property.Value.PropertyType == typeof(bool)) - property.Value.SetValue(this, true); - - if (property.Value.PropertyType == typeof(string)) - property.Value.SetValue(this, args[++i]); - - if (property.Value.PropertyType == typeof(List)) - { - i++; - var l = new List(16); - while (i < args.Length && !args[i].StartsWith(_argPrefix)) - { - if (Guid.TryParse(args[i], out Guid g)) - { - l.Add(g); - _log.Info($"added plugin {g}"); - } - else - _log.Warn($"Failed to parse GUID {args[i]}"); - i++; - } - property.Value.SetValue(this, l); - } - } - } - catch - { - Console.WriteLine($"Error parsing arg {argName}"); - } - } - } - - return true; - - } - - public class ArgAttribute : Attribute - { - public string Name { get; } - public string Description { get; } - public ArgAttribute(string name, string description) - { - Name = name; - Description = description; - } - } - } -}