/// <summary> /// Adding new command to the existings commands. /// Checks all command attributes, and give warns on duplicates. /// </summary> /// <param name="newCommand">The new command</param> /// <returns>true if new command is unique, else false (with console message)</returns> internal static bool AddToCommands(ConsoleCommand newCommand) { bool returnValue = true; string oldPrefix = ConsoleOutput.GetPrefix(); ConsoleOutput.SetPrefix(oldPrefix.Replace("> ", "\t")); try { // Already used command string -> message ConsoleCommand blockingCommand = Commands.FirstOrDefault(cmd => cmd.Command.ToLower() == newCommand.Command.ToLower()); if (blockingCommand != null) { ConsoleOutput.WriteLine(ConsoleType.Warn, $"Command duplicate: ~c~{blockingCommand.FullName()}"); returnValue = false; } // Already used alias command string -> message blockingCommand = Commands.FirstOrDefault(cmd => cmd.CommandAliases.Contains(newCommand.Command) || cmd.CommandAliases.Any(sa => newCommand.CommandAliases .Select(s => s.ToLower()).Contains(sa))); if (blockingCommand != null) { ConsoleOutput.WriteLine(ConsoleType.Warn, $"Alias duplicate: ~c~{blockingCommand.FullName()}"); returnValue = false; } Commands.Add(newCommand); return(returnValue); } finally { ConsoleOutput.SetPrefix(oldPrefix); } }
/// <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); } } }