diff --git a/Application/Application.csproj b/Application/Application.csproj index 000c5ede5..0165f96fb 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -6,7 +6,7 @@ 2.1.5 false RaidMax.IW4MAdmin.Application - 2.2.4.3 + 2.2.4.4 RaidMax Forever None IW4MAdmin @@ -31,8 +31,8 @@ true true - 2.2.4.3 - 2.2.4.3 + 2.2.4.4 + 2.2.4.4 diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 693ee5bdb..bc6519036 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -210,6 +210,25 @@ namespace IW4MAdmin.Application { Running = true; + + #region PLUGINS + SharedLibraryCore.Plugins.PluginImporter.Load(this); + + foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins) + { + try + { + await Plugin.OnLoadAsync(this); + } + + catch (Exception ex) + { + Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_PLUGIN"]} {Plugin.Name}"); + Logger.WriteDebug(ex.GetExceptionInfo()); + } + } + #endregion + #region CONFIG var config = ConfigHandler.Configuration(); @@ -232,7 +251,18 @@ namespace IW4MAdmin.Application do { - newConfig.Servers.Add((ServerConfiguration)new ServerConfiguration().Generate()); + var serverConfig = new ServerConfiguration(); + foreach (var parser in AdditionalRConParsers) + { + serverConfig.AddRConParser(parser); + } + + foreach (var parser in AdditionalEventParsers) + { + serverConfig.AddEventParser(parser); + } + + newConfig.Servers.Add((ServerConfiguration)serverConfig.Generate()); } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["SETUP_SERVER_SAVE"])); config = newConfig; @@ -275,24 +305,6 @@ namespace IW4MAdmin.Application PrivilegedClients = (await ClientSvc.GetPrivilegedClients()).ToDictionary(_client => _client.ClientId); #endregion - #region PLUGINS - SharedLibraryCore.Plugins.PluginImporter.Load(this); - - foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins) - { - try - { - await Plugin.OnLoadAsync(this); - } - - catch (Exception ex) - { - Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_PLUGIN"]} {Plugin.Name}"); - Logger.WriteDebug(ex.GetExceptionInfo()); - } - } - #endregion - #region COMMANDS if (ClientSvc.GetOwners().Result.Count == 0) { diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index d477b9ad4..b84ff0eff 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -42,7 +42,7 @@ namespace IW4MAdmin.Application.RconParsers Configuration.Status.AddMapping(ParserRegex.GroupType.RConName, 5); Configuration.Status.AddMapping(ParserRegex.GroupType.RConIpAddress, 7); - Configuration.Dvar.Pattern = "^\"(.+)\" is: \"(.+)\" default: \"(.+)\"\n(?:latched: \"(.+)\"\n)? *(.+)$"; + Configuration.Dvar.Pattern = "^\"(.+)\" is: \"(.+)\" default: \"(.+)?\"\n(?:latched: \"(.+)?\"\n)? *(.+)$"; Configuration.Dvar.AddMapping(ParserRegex.GroupType.RConDvarName, 1); Configuration.Dvar.AddMapping(ParserRegex.GroupType.RConDvarValue, 2); Configuration.Dvar.AddMapping(ParserRegex.GroupType.RConDvarDefaultValue, 3); diff --git a/SharedLibraryCore/Configuration/ServerConfiguration.cs b/SharedLibraryCore/Configuration/ServerConfiguration.cs index 4e8aa744a..a302787bc 100644 --- a/SharedLibraryCore/Configuration/ServerConfiguration.cs +++ b/SharedLibraryCore/Configuration/ServerConfiguration.cs @@ -1,6 +1,7 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; +using System.Linq; namespace SharedLibraryCore.Configuration { @@ -11,11 +12,22 @@ namespace SharedLibraryCore.Configuration public string Password { get; set; } public IList Rules { get; set; } public IList AutoMessages { get; set; } - public bool UseT6MParser { get; set; } public string ManualLogPath { get; set; } public string CustomParserVersion { get; set; } public int ReservedSlotNumber { get; set; } + private readonly IList rconParsers; + private readonly IList eventParsers; + + public ServerConfiguration() + { + rconParsers = new List(); + eventParsers = new List(); + } + + public void AddRConParser(IRConParser parser) => rconParsers.Add(parser); + public void AddEventParser(IEventParser parser) => eventParsers.Add(parser); + public IBaseConfiguration Generate() { var loc = Utilities.CurrentLocalization.LocalizationIndex; @@ -38,9 +50,24 @@ namespace SharedLibraryCore.Configuration Password = Utilities.PromptString(loc["SETUP_SERVER_RCON"]); AutoMessages = new List(); Rules = new List(); - UseT6MParser = Utilities.PromptBool(loc["SETUP_SERVER_USET6M"]); ReservedSlotNumber = loc["SETUP_SERVER_RESERVEDSLOT"].PromptInt(null, 0, 32); + var parserVersions = rconParsers.Select(_parser => _parser.Version).ToArray(); + var selection = Utilities.PromptSelection(loc["SETUP_SERVER_RCON_PARSER_VERSION"], $"{loc["SETUP_PROMPT_DEFAULT"]} (IW4x)", null, parserVersions); + + if (selection.Item1 > 0) + { + CustomParserVersion = selection.Item2; + } + + parserVersions = eventParsers.Select(_parser => _parser.Version).ToArray(); + selection = Utilities.PromptSelection(loc["SETUP_SERVER_EVENT_PARSER_VERSION"], $"{loc["SETUP_PROMPT_DEFAULT"]} (IW4x)", null, parserVersions); + + if (selection.Item1 > 0) + { + CustomParserVersion = selection.Item2; + } + return this; } diff --git a/SharedLibraryCore/Helpers/Vector3.cs b/SharedLibraryCore/Helpers/Vector3.cs index b7850ecdd..d38b6d86d 100644 --- a/SharedLibraryCore/Helpers/Vector3.cs +++ b/SharedLibraryCore/Helpers/Vector3.cs @@ -21,6 +21,7 @@ namespace SharedLibraryCore.Helpers { } + public Vector3(float x, float y, float z) { X = x; diff --git a/SharedLibraryCore/RCon/Connection.cs b/SharedLibraryCore/RCon/Connection.cs index b09012c21..5d09f3e3a 100644 --- a/SharedLibraryCore/RCon/Connection.cs +++ b/SharedLibraryCore/RCon/Connection.cs @@ -81,13 +81,13 @@ namespace SharedLibraryCore.RCon { case StaticHelpers.QueryType.GET_DVAR: waitForResponse |= true; - payload = (string.Format(Config.CommandPrefixes.RConGetDvar, RConPassword, parameters + '\0')).Select(Convert.ToByte).ToArray(); + payload = Utilities.EncodingType.GetBytes(string.Format(Config.CommandPrefixes.RConGetDvar, RConPassword, parameters + '\0')); break; case StaticHelpers.QueryType.SET_DVAR: - payload = (string.Format(Config.CommandPrefixes.RConSetDvar, RConPassword, parameters + '\0')).Select(Convert.ToByte).ToArray(); + payload = Utilities.EncodingType.GetBytes(string.Format(Config.CommandPrefixes.RConSetDvar, RConPassword, parameters + '\0')); break; case StaticHelpers.QueryType.COMMAND: - payload = (string.Format(Config.CommandPrefixes.RConCommand, RConPassword, parameters + '\0')).Select(Convert.ToByte).ToArray(); + payload = Utilities.EncodingType.GetBytes(string.Format(Config.CommandPrefixes.RConCommand, RConPassword, parameters + '\0')); break; case StaticHelpers.QueryType.GET_STATUS: waitForResponse |= true; diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index b030f25f6..08cb7052a 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -492,6 +492,45 @@ namespace SharedLibraryCore return response != 0 ? response == 'y' : defaultValue; } + /// + /// prompt user to make a selection + /// + /// type of selection + /// question to prompt the user with + /// default value to set if no input is entered + /// description of the question's value + /// array of possible selections (should be able to convert to string) + /// + public static Tuple PromptSelection(string question, T defaultValue, string description = null, params T[] selections) + { + bool hasDefault = false; + + if (defaultValue != null) + { + hasDefault = true; + selections = (new T[] { defaultValue }).Union(selections).ToArray(); + } + + Console.WriteLine($"{question}{(string.IsNullOrEmpty(description) ? "" : $" [{ description}:]")}"); + Console.WriteLine(new string('=', 52)); + for (int index = 0; index < selections.Length; index++) + { + Console.WriteLine($"{(hasDefault ? index : index + 1)}] {selections[index]}"); + } + Console.WriteLine(new string('=', 52)); + + int selectionIndex = PromptInt(CurrentLocalization.LocalizationIndex["SETUP_PROMPT_MAKE_SELECTION"], null, hasDefault ? 0 : 1, selections.Length, hasDefault ? 0 : (int?)null); + + if (!hasDefault) + { + selectionIndex--; + } + + T selection = selections[selectionIndex ]; + + return Tuple.Create(selectionIndex, selection); + } + /// /// prompt user to enter a number /// @@ -503,7 +542,7 @@ namespace SharedLibraryCore /// integer from user's input public static int PromptInt(this string question, string description = null, int minValue = 0, int maxValue = int.MaxValue, int? defaultValue = null) { - Console.Write($"{question}{(string.IsNullOrEmpty(description) ? "" : $" ({description})")}{(defaultValue == null ? "" : $" [{CurrentLocalization.LocalizationIndex["SETUP_PROMPT_DEFAULT"]} {defaultValue.Value.ToString()}")}]: "); + Console.Write($"{question}{(string.IsNullOrEmpty(description) ? "" : $" ({description})")}{(defaultValue == null ? "" : $" [{CurrentLocalization.LocalizationIndex["SETUP_PROMPT_DEFAULT"]} {defaultValue.Value.ToString()}]")}: "); int response; string inputOrDefault()