private static void ParseConsoleString(string consoleString, CancelEventArgs cancelEventArgs) { List <string> consoleStringParts = consoleString.Split(' ').ToList(); foreach (ConsoleCommand command in Commands) { // console string not command -> continue; if (command.Command.ToLower() != consoleStringParts[0].ToLower() && !command.CommandAliases.Select(ca => ca.ToLower()) .Contains(consoleStringParts[0].ToLower())) { continue; } // Cancle event cancelEventArgs.Cancel = true; // Remove command string enteredCommand = consoleStringParts[0]; consoleStringParts.Remove(enteredCommand); // Check for parameters List <object> parameterValues = new List <object>(); ParameterInfo[] commandParameters = command.MethodInfo.GetParameters(); string currentParameterString = string.Empty; for (int i = 0; i < commandParameters.Length; i++) { // No more string parameters -> break; if (consoleStringParts.FirstOrDefault() == null) { break; } // append or set string parameters currentParameterString += consoleStringParts.FirstOrDefault(); consoleStringParts.Remove(currentParameterString); // String argument with quote -> wait for end quote. if (currentParameterString.StartsWith("\"")) { if (!currentParameterString.EndsWith("\"")) { i--; continue; } // Remove quotes currentParameterString = currentParameterString .Remove(currentParameterString.Length - 1, 1) .Remove(0, 1); } // Try parse & reset string try { // Barse boolean parameter for Convert functions if (commandParameters[i].ParameterType == typeof(bool)) { if (currentParameterString == "1") { currentParameterString = "true"; } else if (currentParameterString == "0") { currentParameterString = "false"; } } object parameterValue = Convert.ChangeType(currentParameterString, commandParameters[i].ParameterType); currentParameterString = string.Empty; if (parameterValue == null) { break; } parameterValues.Add(parameterValue); } catch (InvalidCastException) { ConsoleOutput.WriteLine(ConsoleType.Error, $"The type ~w~{commandParameters[i].ParameterType}~;~ can't be used as command parameter!"); return; } catch { ConsoleOutput.WriteLine(ConsoleType.Error, $"Invalid type given for parameter {commandParameters[i].Name}."); return; } } // Not enough parameter values -> message & next; if (commandParameters.Count(info => !info.IsOptional) > parameterValues.Count) { ConsoleOutput.WriteLine(ConsoleType.ConsoleCommand, $"Incorrect parameter values for the command ~o~{enteredCommand}~;~. " + $"Type ~b~\"/help {enteredCommand}\"~;~ for more information."); return; } // Add optional parameters if not given, to parametersValues if (commandParameters.Length != parameterValues.Count) { for (int i = commandParameters.Length - parameterValues.Count; i < commandParameters.Length; i++) { parameterValues.Add(commandParameters[i].DefaultValue); } } //TODO: check for optional parameters needed // Invoke command command.MethodInfo.Invoke(command.ClassInstance, parameterValues.ToArray()); return; } ConsoleOutput.WriteLine(ConsoleType.Error, $"~w~No command found for ~r~\"{consoleStringParts[0]}\"~w~!"); }
/// <summary> /// Inspects a class for Commands. /// </summary> /// <param name="moduleInstance">The instance of the module wich should be inspected.</param> internal static void InspectModule(object moduleInstance) { List <ConsoleCommand> validCommands = new List <ConsoleCommand>(); List <ConsoleCommand> invalidCommands = new List <ConsoleCommand>(); // Parse commands direct in module ParseCommands(moduleInstance); // Parse all field & Property infos foreach (FieldInfo fieldInfo in moduleInstance.GetType().GetFields()) { ParseMemberInfo(null, fieldInfo, moduleInstance); } foreach (PropertyInfo propertyInfo in moduleInstance.GetType().GetProperties()) { ParseMemberInfo(propertyInfo, null, moduleInstance); } // Parse static commands ParseStaticCommands(); // Check for invalid commands & write message if given ParseInvalidCommands(); if (invalidCommands.Any()) { ConsoleOutput.SetPrefix(ConsoleOutput.GetPrefix().Replace(">", "~r~!")); foreach (ConsoleCommand invalidCommand in invalidCommands) { ConsoleOutput.WriteLine(ConsoleType.ConsoleCommand, "~r~" + invalidCommand.Command + "~c~ " + invalidCommand.FullName()); } ConsoleOutput.SetPrefix(ConsoleOutput.GetPrefix().Replace("~r~!", ">")); } // Register commands if (validCommands.Any()) { foreach (ConsoleCommand command in validCommands) { if (AddToCommands(command)) // On working command { ConsoleOutput.SetPrefix(ConsoleOutput.GetPrefix().Replace(">", "~g~+")); // Highlight important commands string commandColorCode = command.ImportantCommand ? "~#f66e00~" : "~g~"; // Command aliases string aliasString = $"{(command.CommandAliases.Any() ? $"~w~({commandColorCode}" : "")}{string.Join($"~w~, {commandColorCode}", command.CommandAliases)}{(command.CommandAliases.Any() ? "~w~)" : "")}"; ConsoleOutput.WriteLine(ConsoleType.ConsoleCommand, $"{commandColorCode}{command.Command} {aliasString} ~c~{command.FullName()}"); // Description if (!string.IsNullOrEmpty(command.Description)) { string currentPrefix = ConsoleOutput.GetPrefix(); ConsoleOutput.SetPrefix("\t\t~c~ > ~;~"); ConsoleOutput.WriteLine(ConsoleType.ConsoleCommand, command.Description); ConsoleOutput.SetPrefix(currentPrefix); } } else // on warnings { ConsoleOutput.SetPrefix(ConsoleOutput.GetPrefix().Replace(">", "~o~?")); ConsoleOutput.WriteLine(ConsoleType.ConsoleCommand, "~o~" + command.Command + "~c~ " + command.FullName()); } ConsoleOutput.SetPrefix(ConsoleOutput.GetPrefix().Replace("~g~+", ">").Replace("~o~?", ">")); } } void ParseInvalidCommands() { foreach (Type type in moduleInstance.GetType().Assembly.GetTypes()) { foreach (MethodInfo methodInfo in type.GetMethods()) { object[] attributes = methodInfo.GetCustomAttributes(typeof(ConsoleCommand), true); if (attributes.Length <= 0) { continue; } foreach (object commandObject in attributes) { // Method is registered as valid -> next. if (validCommands.Any(cmd => cmd.MethodInfo == methodInfo)) { continue; } ConsoleCommand command = (ConsoleCommand)commandObject; // Save MethodInfo and Class instance command.MethodInfo = methodInfo; invalidCommands.Add(command); } } } } void ParseStaticCommands() { foreach (Type type in moduleInstance.GetType().Assembly.GetTypes()) { foreach (MethodInfo methodInfo in type.GetMethods() .Where(info => info.IsStatic && info.IsPublic && !info.IsConstructor)) { object[] attributes = methodInfo.GetCustomAttributes(typeof(ConsoleCommand), true); if (attributes.Length <= 0) { continue; } foreach (object commandObject in attributes) { ConsoleCommand command = (ConsoleCommand)commandObject; // Save MethodInfo and Class instance command.MethodInfo = methodInfo; command.ClassInstance = null; validCommands.Add(command); } } } } void ParseCommands(object instance) { foreach (MethodInfo methodInfo in instance.GetType().GetMethods() .Where(info => !info.IsStatic && info.IsPublic && !info.IsConstructor)) { object[] attributes = methodInfo.GetCustomAttributes(typeof(ConsoleCommand), true); if (attributes.Length <= 0) { continue; } foreach (object commandObject in attributes) { ConsoleCommand command = (ConsoleCommand)commandObject; // Save MethodInfo and Class instance command.MethodInfo = methodInfo; command.ClassInstance = instance; validCommands.Add(command); } } } void ParseMemberInfo(PropertyInfo propertyInfo, FieldInfo fieldInfo, object classInstance) { object instance = propertyInfo?.GetValue(classInstance) ?? fieldInfo?.GetValue(classInstance); if (instance == null || instance.GetType().Assembly != moduleInstance.GetType().Assembly || !instance.GetType().IsClass) { return; } // Search for commands ParseCommands(instance); foreach (FieldInfo field in instance.GetType().GetFields()) { ParseMemberInfo(null, field, instance); } foreach (PropertyInfo property in instance.GetType().GetProperties()) { ParseMemberInfo(property, null, instance); } } }