mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-22 16:48:21 +01:00
This commit is contained in:
parent
d26cbfbd14
commit
01cba2a508
@ -65,7 +65,7 @@ public class CommandDescription {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance for internal use.
|
||||
* Create an instance.
|
||||
*
|
||||
* @param labels List of command labels.
|
||||
* @param description Command description.
|
||||
@ -108,7 +108,7 @@ public class CommandDescription {
|
||||
* @return All relative labels.
|
||||
*/
|
||||
public List<String> getLabels() {
|
||||
return this.labels;
|
||||
return labels;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,23 +145,34 @@ public class CommandDescription {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of parents that precede the command description.
|
||||
*
|
||||
* @return The number of parents, e.g. for "/authme abc def" the parent count is 2 ("/authme abc", "/authme")
|
||||
*/
|
||||
public int getParentCount() {
|
||||
if (parent == null) {
|
||||
return 0;
|
||||
}
|
||||
return parent.getParentCount() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all command children.
|
||||
*
|
||||
* @return Command children.
|
||||
*/
|
||||
public List<CommandDescription> getChildren() {
|
||||
return this.children;
|
||||
return children;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all arguments the command takes.
|
||||
*
|
||||
* @return Command arguments.
|
||||
*/
|
||||
public List<CommandArgumentDescription> getArguments() {
|
||||
return this.arguments;
|
||||
return arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,14 +193,13 @@ public class CommandDescription {
|
||||
return detailedDescription;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the permissions required to execute the command.
|
||||
*
|
||||
* @return The command permissions, or null if none are required to execute the command.
|
||||
*/
|
||||
public CommandPermissions getCommandPermissions() {
|
||||
return this.permissions;
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,11 +128,15 @@ public class CommandHandler {
|
||||
|
||||
// Show the command argument help
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!");
|
||||
// TODO: Define showHelp(CommandSender, CommandDescription, List<String>, boolean, boolean, ...)
|
||||
List<String> lines = HelpProvider.printHelp(result, HelpProvider.SHOW_ARGUMENTS);
|
||||
for (String line : lines) {
|
||||
sender.sendMessage(line);
|
||||
}
|
||||
|
||||
List<String> labels = result.getLabels();
|
||||
HelpProvider.showHelp(sender, command, labels, true, false, true, false, false, false);
|
||||
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + labels.get(0)
|
||||
+ " help " + CommandUtils.labelsToString(labels.subList(1, labels.size())));
|
||||
String childLabel = labels.size() >= 2 ? labels.get(1) : "";
|
||||
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE
|
||||
+ "/" + labels.get(0) + " help " + childLabel);
|
||||
}
|
||||
|
||||
// TODO ljacqu 20151212: Remove me once I am a MessageKey
|
||||
|
@ -1,141 +1,234 @@
|
||||
package fr.xephi.authme.command.help;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import fr.xephi.authme.command.CommandArgumentDescription;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
import fr.xephi.authme.command.CommandPermissions;
|
||||
import fr.xephi.authme.command.CommandUtils;
|
||||
import fr.xephi.authme.command.FoundCommandResult;
|
||||
import fr.xephi.authme.permission.DefaultPermission;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
||||
import fr.xephi.authme.util.CollectionUtils;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Help syntax generator for AuthMe commands.
|
||||
*/
|
||||
public class HelpProvider {
|
||||
public final class HelpProvider {
|
||||
|
||||
/**
|
||||
* Show help for a specific command.
|
||||
*
|
||||
* @param sender The command sender the help needs to be shown to.
|
||||
* @param reference The command reference to the help command.
|
||||
* @param helpQuery The query to show help for.
|
||||
*/
|
||||
public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery) {
|
||||
showHelp(sender, reference, helpQuery, true, true, true, true, true, true);
|
||||
// --- Bit flags ---
|
||||
/** Set to <i>not</i> show the command. */
|
||||
public static final int HIDE_COMMAND = 0x001;
|
||||
/** Set to show the detailed description of a command. */
|
||||
public static final int SHOW_LONG_DESCRIPTION = 0x002;
|
||||
/** Set to include the arguments the command takes. */
|
||||
public static final int SHOW_ARGUMENTS = 0x004;
|
||||
/** Set to show the permissions required to execute the command. */
|
||||
public static final int SHOW_PERMISSIONS = 0x008;
|
||||
/** Set to show alternative labels for the command. */
|
||||
public static final int SHOW_ALTERNATIVES = 0x010;
|
||||
/** Set to show the child commands of the command. */
|
||||
public static final int SHOW_CHILDREN = 0x020;
|
||||
|
||||
/** Shortcut for setting all options apart from {@link HelpProvider#HIDE_COMMAND}. */
|
||||
public static final int ALL_OPTIONS = ~HIDE_COMMAND;
|
||||
|
||||
private HelpProvider() {
|
||||
}
|
||||
|
||||
public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery,
|
||||
boolean showCommand, boolean showDescription, boolean showArguments,
|
||||
boolean showPermissions, boolean showAlternatives, boolean showCommands) {
|
||||
showHelp(sender, reference.getList(), helpQuery.getList(), showCommand, showDescription, showArguments,
|
||||
showPermissions, showAlternatives, showCommands);
|
||||
public static List<String> printHelp(FoundCommandResult foundCommand, int options) {
|
||||
return printHelp(foundCommand, null, null, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show help for a specific command.
|
||||
*
|
||||
* @param sender The command sender the help needs to be shown to.
|
||||
* @param reference The command reference to the help command.
|
||||
* @param helpQuery The query to show help for.
|
||||
* @param showCommand True to show the command.
|
||||
* @param showDescription True to show the command description, both the short and detailed description.
|
||||
* @param showArguments True to show the command argument help.
|
||||
* @param showPermissions True to show the command permission help.
|
||||
* @param showAlternatives True to show the command alternatives.
|
||||
* @param showCommands True to show the child commands.
|
||||
*/
|
||||
public static void showHelp(CommandSender sender, List<String> reference, List<String> helpQuery,
|
||||
boolean showCommand, boolean showDescription, boolean showArguments,
|
||||
boolean showPermissions, boolean showAlternatives, boolean showCommands) {
|
||||
// Find the command for this help query, one with and one without a prefixed base command
|
||||
FoundCommandResult result = AuthMe.getInstance().getCommandHandler().findCommand(new CommandParts(helpQuery.getList()));
|
||||
|
||||
// TODO ljacqu 20151204 Fix me to nicer code
|
||||
List<String> parts = new ArrayList<>(helpQuery.getList());
|
||||
parts.add(0, reference.get(0));
|
||||
CommandParts commandReferenceOther = new CommandParts(parts);
|
||||
|
||||
FoundCommandResult resultOther = AuthMe.getInstance().getCommandHandler().findCommand(commandReferenceOther);
|
||||
if (resultOther != null) {
|
||||
if (result == null)
|
||||
result = resultOther;
|
||||
|
||||
else if (result.getDifference() > resultOther.getDifference())
|
||||
result = resultOther;
|
||||
// sender and permissions manager may be null if SHOW_PERMISSIONS is not set
|
||||
public static List<String> printHelp(FoundCommandResult foundCommand, CommandSender sender,
|
||||
PermissionsManager permissionsManager, int options) {
|
||||
if (foundCommand.getCommandDescription() == null) {
|
||||
return singletonList(ChatColor.DARK_RED + "Failed to retrieve any help information!");
|
||||
}
|
||||
|
||||
// Make sure a result was found
|
||||
if (result == null) {
|
||||
// Show a warning message
|
||||
sender.sendMessage(ChatColor.DARK_RED + "" + ChatColor.ITALIC + helpQuery);
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Couldn't show any help information for this help query.");
|
||||
List<String> lines = new ArrayList<>();
|
||||
lines.add(ChatColor.GOLD + "==========[ " + Settings.helpHeader + " HELP ]==========");
|
||||
|
||||
CommandDescription command = foundCommand.getCommandDescription();
|
||||
// TODO ljacqu 20151212: Remove immutability once class is stable. We don't want mutability but the overhead
|
||||
// isn't worth it either. This is just a temporary safeguard during development
|
||||
List<String> labels = ImmutableList.copyOf(foundCommand.getLabels());
|
||||
|
||||
if (!hasFlag(HIDE_COMMAND, options)) {
|
||||
printCommand(command, labels, lines); // FIXME: Pass `correctLabels` and not `labels`
|
||||
}
|
||||
if (hasFlag(SHOW_LONG_DESCRIPTION, options)) {
|
||||
printDetailedDescription(command, lines);
|
||||
}
|
||||
if (hasFlag(SHOW_ARGUMENTS, options)) {
|
||||
printArguments(command, lines);
|
||||
}
|
||||
if (hasFlag(SHOW_PERMISSIONS, options) && sender != null && permissionsManager != null) {
|
||||
printPermissions(command, sender, permissionsManager, lines);
|
||||
}
|
||||
if (hasFlag(SHOW_ALTERNATIVES, options)) {
|
||||
printAlternatives(command, labels, lines);
|
||||
}
|
||||
if (hasFlag(SHOW_CHILDREN, options)) {
|
||||
printChildren(command, labels, lines);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static void printCommand(CommandDescription command, List<String> correctLabels, List<String> lines) {
|
||||
// Ensure that we have all labels to go to the command
|
||||
int requiredLabels = command.getParentCount() + 1;
|
||||
List<String> givenLabels = new ArrayList<>(correctLabels);
|
||||
// Only case this is possible: givenLabels.size() == 1 && requiredLabels == 2,
|
||||
// since command.getParentCount() never exceeds 1 in AuthMe
|
||||
// FIXME: Might be smart to put this logic outside and to pass it as `correctLabels`? We will need this at a few
|
||||
// places annotated with a FIXME
|
||||
if (givenLabels.size() < requiredLabels) {
|
||||
givenLabels.add(command.getLabels().get(0));
|
||||
}
|
||||
|
||||
// FIXME: Create highlight logic to mark arguments and the 2nd label as yellow
|
||||
String syntaxLine = "/" + CommandUtils.labelsToString(givenLabels);
|
||||
for (CommandArgumentDescription argument : command.getArguments()) {
|
||||
syntaxLine += " " + formatArgument(argument);
|
||||
}
|
||||
lines.add(syntaxLine);
|
||||
}
|
||||
|
||||
private static void printDetailedDescription(CommandDescription command, List<String> lines) {
|
||||
lines.add(ChatColor.GOLD + "Short Description: " + ChatColor.WHITE + command.getDescription());
|
||||
lines.add(ChatColor.GOLD + "Detailed Description:");
|
||||
lines.add(ChatColor.WHITE + " " + command.getDetailedDescription());
|
||||
}
|
||||
|
||||
private static void printArguments(CommandDescription command, List<String> lines) {
|
||||
if (!command.getArguments().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the command description, and make sure it's valid
|
||||
CommandDescription command = result.getCommandDescription();
|
||||
if (command == null) {
|
||||
// Show a warning message
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Failed to retrieve any help information!");
|
||||
return;
|
||||
}
|
||||
lines.add(ChatColor.GOLD + "Arguments:");
|
||||
for (CommandArgumentDescription argument : command.getArguments()) {
|
||||
StringBuilder argString = new StringBuilder();
|
||||
argString.append(" ").append(ChatColor.YELLOW).append(ChatColor.ITALIC).append(argument.getName())
|
||||
.append(": ").append(ChatColor.WHITE).append(argument.getDescription());
|
||||
|
||||
// Get the proper command reference to use for the help page
|
||||
CommandParts commandReference = command.getCommandReference(result.getLabels());
|
||||
|
||||
// Get the base command
|
||||
String baseCommand = commandReference.get(0);
|
||||
|
||||
// Make sure the difference between the command reference and the actual command isn't too big
|
||||
final double commandDifference = result.getDifference();
|
||||
if (commandDifference > 0.20) {
|
||||
// Show the unknown command warning
|
||||
sender.sendMessage(ChatColor.DARK_RED + "No help found for '" + helpQuery + "'!");
|
||||
|
||||
// Show a command suggestion if available and the difference isn't too big
|
||||
if (commandDifference < 0.75 && result.getCommandDescription() != null) {
|
||||
// Get the suggested command
|
||||
List<String> suggestedCommandParts = CollectionUtils.getRange(
|
||||
result.getCommandDescription().getCommandReference(commandReference).getList(), 1);
|
||||
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + baseCommand
|
||||
+ " help " + CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.YELLOW + "?");
|
||||
if (argument.isOptional()) {
|
||||
argString.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (Optional)");
|
||||
}
|
||||
lines.add(argString.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Show the help command
|
||||
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" + ChatColor.YELLOW + " to view help.");
|
||||
// FIXME: labels is currently assumed to be only the ones leading to the given command, but we have scenarios where
|
||||
// we're guessing the command, so the final label isn't any existing one
|
||||
private static void printAlternatives(CommandDescription command, List<String> labels, List<String> lines) {
|
||||
if (command.getLabels().size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show a message when the command handler is assuming a command
|
||||
if (commandDifference > 0) {
|
||||
// Get the suggested command
|
||||
List<String> suggestedCommandParts = CollectionUtils.getRange(
|
||||
result.getCommandDescription().getCommandReference(commandReference).getList(), 1);
|
||||
// Print the header
|
||||
lines.add(ChatColor.GOLD + "Alternatives:");
|
||||
|
||||
// Show the suggested command
|
||||
sender.sendMessage(ChatColor.DARK_RED + "No help found, assuming '" + ChatColor.GOLD
|
||||
+ CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.DARK_RED + "'!");
|
||||
// Get the label used
|
||||
// fixme this is not correct if help is triggered by incorrect number of arguments
|
||||
final String usedLabel = labels.get(labels.size() - 1);
|
||||
|
||||
// Create a list of alternatives
|
||||
List<String> alternatives = new ArrayList<>();
|
||||
for (String entry : command.getLabels()) {
|
||||
if (!entry.equalsIgnoreCase(usedLabel)) {
|
||||
alternatives.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Print the help header
|
||||
sender.sendMessage(ChatColor.GOLD + "==========[ " + Settings.helpHeader.toUpperCase() + " HELP ]==========");
|
||||
// Sort the alternatives
|
||||
Collections.sort(alternatives, new Comparator<String>() {
|
||||
// TODO ljacqu 20151212: This computes the difference each time anew. It might make sense to compute the
|
||||
// difference once and to store it in some map-like structure (Guava has some interesting ones)
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return Double.compare(StringUtils.getDifference(usedLabel, o1),
|
||||
StringUtils.getDifference(usedLabel, o2));
|
||||
}
|
||||
});
|
||||
|
||||
// Print the command help information
|
||||
if (showCommand)
|
||||
HelpPrinter.printCommand(sender, command, commandReference);
|
||||
if (showDescription)
|
||||
HelpPrinter.printCommandDescription(sender, command);
|
||||
if (showArguments)
|
||||
HelpPrinter.printArguments(sender, command);
|
||||
if (showPermissions)
|
||||
HelpPrinter.printPermissions(sender, command);
|
||||
if (showAlternatives)
|
||||
HelpPrinter.printAlternatives(sender, command, commandReference);
|
||||
if (showCommands)
|
||||
HelpPrinter.printChildren(sender, command, commandReference);
|
||||
// Print each alternative with proper syntax
|
||||
for (String alternative : alternatives) {
|
||||
// fixme add highlight functionality (see commented old line)
|
||||
// sender.sendMessage(" " + _HelpSyntaxHelper.getCommandSyntax(command, commandReference, alternative, true));
|
||||
lines.add(" " + CommandUtils.labelsToString(labels) + " " + alternative);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printPermissions(CommandDescription command, CommandSender sender,
|
||||
PermissionsManager permissionsManager, List<String> lines) {
|
||||
CommandPermissions permissions = command.getCommandPermissions();
|
||||
if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) {
|
||||
return;
|
||||
}
|
||||
lines.add(ChatColor.GOLD + "Permissions:");
|
||||
|
||||
for (PermissionNode node : permissions.getPermissionNodes()) {
|
||||
boolean hasPermission = permissionsManager.hasPermission(sender, node);
|
||||
final String nodePermsString = "" + ChatColor.GRAY + ChatColor.ITALIC
|
||||
+ (hasPermission ? " (You have permission)" : " (No permission)");
|
||||
lines.add(" " + ChatColor.YELLOW + ChatColor.ITALIC + node.getNode() + nodePermsString);
|
||||
}
|
||||
|
||||
// Addendum to the line to specify whether the sender has permission or not when default is OP_ONLY
|
||||
final DefaultPermission defaultPermission = permissions.getDefaultPermission();
|
||||
String addendum = "";
|
||||
if (DefaultPermission.OP_ONLY.equals(defaultPermission)) {
|
||||
addendum = PermissionsManager.evaluateDefaultPermission(defaultPermission, sender)
|
||||
? " (You have permission)"
|
||||
: " (No permission)";
|
||||
}
|
||||
lines.add(ChatColor.GOLD + "Default: " + ChatColor.GRAY + ChatColor.ITALIC
|
||||
+ defaultPermission.getTitle() + addendum);
|
||||
|
||||
// Evaluate if the sender has permission to the command
|
||||
if (permissionsManager.hasPermission(sender, command)) {
|
||||
lines.add(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "You have permission");
|
||||
} else {
|
||||
lines.add(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No permission");
|
||||
}
|
||||
}
|
||||
|
||||
private static void printChildren(CommandDescription command, List<String> parentLabels, List<String> lines) {
|
||||
if (command.getChildren().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lines.add(ChatColor.GOLD + "Commands:");
|
||||
String parentCommandPath = CommandUtils.labelsToString(parentLabels);
|
||||
for (CommandDescription child : command.getChildren()) {
|
||||
lines.add(" " + parentCommandPath + child.getLabels().get(0)
|
||||
+ ChatColor.GRAY + ChatColor.ITALIC + ": " + child.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatArgument(CommandArgumentDescription argument) {
|
||||
if (argument.isOptional()) {
|
||||
return " [" + argument.getName() + "]";
|
||||
}
|
||||
return " <" + argument.getName() + ">";
|
||||
}
|
||||
|
||||
private static boolean hasFlag(int flag, int options) {
|
||||
return (flag & options) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,11 +6,28 @@ package fr.xephi.authme.permission;
|
||||
public enum DefaultPermission {
|
||||
|
||||
/** No one can execute the command. */
|
||||
NOT_ALLOWED,
|
||||
NOT_ALLOWED("No permission"),
|
||||
|
||||
/** Only players with the OP status may execute the command. */
|
||||
OP_ONLY,
|
||||
OP_ONLY("OP's only"),
|
||||
|
||||
/** The command can be executed by anyone. */
|
||||
ALLOWED
|
||||
ALLOWED("Everyone allowed");
|
||||
|
||||
/** Textual representation of the default permission. */
|
||||
private final String title;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param title The textual representation
|
||||
*/
|
||||
DefaultPermission(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/** Return the textual representation. */
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user