AbstractCommand.java
package com.hypixel.hytale.server.core.command.system;
import com.hypixel.hytale.common.util.StringUtil;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.protocol.GameMode;
import com.hypixel.hytale.server.core.Constants;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.command.system.arguments.system.AbstractOptionalArg;
import com.hypixel.hytale.server.core.command.system.arguments.system.ArgWrapper;
import com.hypixel.hytale.server.core.command.system.arguments.system.Argument;
import com.hypixel.hytale.server.core.command.system.arguments.system.DefaultArg;
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg;
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
import com.hypixel.hytale.server.core.command.system.arguments.system.WrappedArg;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgumentType;
import com.hypixel.hytale.server.core.command.system.arguments.types.ListArgumentType;
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractCommandCollection;
import com.hypixel.hytale.server.core.command.system.exceptions.GeneralCommandException;
import com.hypixel.hytale.server.core.modules.i18n.I18nModule;
import com.hypixel.hytale.server.core.plugin.PluginBase;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectBooleanPair;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class AbstractCommand {
@Nonnull
public static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
public static final String[] EMPTY_STRING_ARRAY = new String[0];
@Nonnull
private static final Message MESSAGE_COMMANDS_HELP_NO_PERMISSIBLE_SUB_COMMAND = Message.translation("server.commands.help.noPermissibleSubCommand");
@Nonnull
private static final Message MESSAGE_COMMANDS_PARSING_ERROR_NO_PERMISSION_FOR_COMMAND = Message.translation("server.commands.parsing.error.noPermissionForCommand");
@Nonnull
private static final Message MESSAGE_COMMANDS_PARSING_ERROR_ATTEMPTED_UNSAFE = Message.translation("server.commands.parsing.error.attemptedUnsafe");
@Nonnull
private static final Message MESSAGE_COMMANDS_PARSING_USAGE_REQUIRES_CONFIRMATION = Message.translation("server.commands.parsing.usage.requiresConfirmation");
@Nonnull
private static final Message MESSAGE_COMMAND_SINGLEPLAYER = Message.translation("server.commands.parsing.error.unavailableInSingleplayer");
@Nonnull
static final String CONFIRM_ARG_TAG = "confirm";
@Nonnull
private static final String COLOR_STRING_ARG_REQUIRED = "#C1E0FF";
@Nonnull
private static final String COLOR_STRING_ARG_OPTIONAL = "#7E9EBC";
private AbstractCommand parentCommand;
@Nullable
private final String name;
@Nonnull
private final Set<String> aliases;
private final String description;
@Nonnull
private final List<RequiredArg<?>> requiredArguments;
@Nonnull
private final Map<String, AbstractOptionalArg<?, ?>> optionalArguments;
private AbbreviationMap<AbstractOptionalArg<?, ?>> argumentAbbreviationMap;
@Nonnull
private final Map<String, AbstractCommand> subCommands;
@Nonnull
private final Map<String, String> subCommandsAliases;
@Nonnull
private final Int2ObjectMap<AbstractCommand> variantCommands;
@Nullable
private CommandOwner owner;
@Nullable
private String permission;
@Nullable
private List<String> permissionGroups;
private int totalNumRequiredParameters;
private final boolean requiresConfirmation;
private boolean unavailableInSingleplayer;
private boolean allowsExtraArguments;
private boolean hasBeenRegistered;
protected AbstractCommand(@Nullable String name, @Nullable String description, boolean requiresConfirmation) {
this.aliases = new HashSet();
this.requiredArguments = new ObjectArrayList<RequiredArg<?>>();
this.optionalArguments = new Object2ObjectOpenHashMap<String, AbstractOptionalArg<?, ?>>();
this.subCommands = new LinkedHashMap();
this.subCommandsAliases = new LinkedHashMap();
this.variantCommands = new Int2ObjectOpenHashMap<AbstractCommand>();
this.name = name == null ? null : name.toLowerCase();
this.description = description;
this.requiresConfirmation = requiresConfirmation;
if (requiresConfirmation) {
this.registerOptionalArg(new FlagArg(this, "confirm", ""));
}
}
protected AbstractCommand(@Nullable String name, @Nullable String description) {
this(name, description, false);
}
protected AbstractCommand(@Nullable String description) {
this((String)null, description);
}
public void setOwner(@Nonnull CommandOwner owner) {
this.owner = owner;
if (this.permission == null && this.canGeneratePermission()) {
this.permission = this.generatePermission();
}
for(AbstractCommand subCommand : this.subCommands.values()) {
subCommand.setOwner(owner);
}
for(AbstractCommand variantCommand : this.variantCommands.values()) {
variantCommand.setOwner(owner);
}
}
protected boolean canGeneratePermission() {
return true;
}
@Nullable
protected String generatePermissionNode() {
return this.name == null ? null : this.name.toLowerCase();
}
@Nonnull
private String generatePermission() {
String selfNode = this.generatePermissionNode();
if (this.parentCommand != null) {
String parentPermission = this.parentCommand.permission == null ? this.parentCommand.generatePermission() : this.parentCommand.permission;
String generatedPermission;
if (selfNode != null && !selfNode.isEmpty()) {
generatedPermission = parentPermission + "." + selfNode;
} else {
generatedPermission = parentPermission;
}
((HytaleLogger.Api)LOGGER.atFine()).log("Generated missing permission '" + generatedPermission + "'.");
return generatedPermission;
} else {
CommandOwner generatedPermission = this.owner;
if (generatedPermission instanceof PluginBase) {
PluginBase plugin = (PluginBase)generatedPermission;
String var10000 = plugin.getBasePermission();
return var10000 + ".command." + selfNode;
} else if (this.owner instanceof CommandManager) {
return "hytale.system.command." + selfNode;
} else {
throw new IllegalArgumentException("Unknown owner type, please use PluginBase or CommandManager");
}
}
}
@Nullable
public List<String> getPermissionGroups() {
return this.permissionGroups;
}
protected void setPermissionGroups(@Nonnull String... groups) {
this.permissionGroups = Arrays.asList(groups);
}
protected void setPermissionGroup(@Nullable GameMode gameMode) {
this.setPermissionGroups(gameMode == null ? null : gameMode.toString());
}
@Nonnull
public Map<String, Set<String>> getPermissionGroupsRecursive() {
Map<String, Set<String>> permissionsByGroup = new Object2ObjectOpenHashMap<String, Set<String>>();
this.putRecursivePermissionGroups(permissionsByGroup);
return permissionsByGroup;
}
public void putRecursivePermissionGroups(@Nonnull Map<String, Set<String>> permissionsByGroup) {
List<String> permissionGroups = this.permissionGroups;
if (permissionGroups == null && this.parentCommand != null) {
permissionGroups = this.parentCommand.permissionGroups;
}
if (permissionGroups != null && this.permission != null) {
for(String group : permissionGroups) {
if (group != null) {
((Set)permissionsByGroup.computeIfAbsent(group, (k) -> new HashSet())).add(this.permission);
}
}
}
for(AbstractCommand subCommand : this.subCommands.values()) {
subCommand.putRecursivePermissionGroups(permissionsByGroup);
}
}
protected void setUnavailableInSingleplayer(boolean unavailableInSingleplayer) {
this.unavailableInSingleplayer = unavailableInSingleplayer;
}
public void setAllowsExtraArguments(boolean allowsExtraArguments) {
this.allowsExtraArguments = allowsExtraArguments;
}
@Nonnull
public MatchResult matches(@Nonnull String language, @Nonnull String search, int termDepth) {
return this.matches(language, search, termDepth, 0);
}
@Nonnull
private MatchResult matches(@Nonnull String language, @Nonnull String search, int termDepth, int depth) {
if (this.name != null && this.name.contains(search)) {
return MatchResult.of(termDepth, depth, 0, this.name, search);
} else {
for(String alias : this.aliases) {
if (alias.contains(search)) {
return MatchResult.of(termDepth, depth, 1, alias, search);
}
}
for(AbstractOptionalArg<?, ?> opt : this.optionalArguments.values()) {
if (opt.getName().contains(search)) {
return MatchResult.of(termDepth, depth, 3, opt.getName(), search);
}
for(String alias : opt.getAliases()) {
if (alias.contains(search)) {
return MatchResult.of(termDepth, depth, 3, alias, search);
}
}
}
for(RequiredArg<?> opt : this.requiredArguments) {
if (opt.getName().contains(search)) {
return MatchResult.of(termDepth, depth, 3, opt.getName(), search);
}
}
if (this.description != null) {
String descriptionMessage = I18nModule.get().getMessage(language, this.description);
if (descriptionMessage != null && descriptionMessage.contains(search)) {
return MatchResult.of(termDepth, depth, 4, descriptionMessage, search);
}
}
for(AbstractOptionalArg<?, ?> opt : this.optionalArguments.values()) {
String description = opt.getDescription();
if (description != null) {
String usageDescription = I18nModule.get().getMessage(language, description);
if (usageDescription != null && usageDescription.contains(search)) {
return MatchResult.of(termDepth, depth, 5, usageDescription, search);
}
}
}
for(AbstractCommand subCommand : this.subCommands.values()) {
MatchResult result = subCommand.matches(language, search, termDepth, depth + 1);
if (result != MatchResult.NONE) {
return result;
}
}
for(AbstractCommand variantCommand : this.variantCommands.values()) {
MatchResult result = variantCommand.matches(language, search, termDepth, depth + 1);
if (result != MatchResult.NONE) {
return result;
}
}
return MatchResult.NONE;
}
}
public void completeRegistration() throws GeneralCommandException {
this.hasBeenRegistered = true;
for(AbstractCommand command : this.subCommands.values()) {
command.completeRegistration();
}
for(AbstractCommand command : this.variantCommands.values()) {
command.completeRegistration();
}
this.validateVariantNumberOfRequiredParameters(new ParseResult(true));
this.validateDefaultArguments(new ParseResult(true));
this.createOptionalArgumentAbbreviationMap();
}
private void createOptionalArgumentAbbreviationMap() {
AbbreviationMap.AbbreviationMapBuilder<AbstractOptionalArg<?, ?>> abbreviationMapBuilder = AbbreviationMap.<AbstractOptionalArg<?, ?>>create();
for(AbstractOptionalArg<?, ?> abstractOptionalArg : this.optionalArguments.values()) {
abbreviationMapBuilder.put(abstractOptionalArg.getName(), abstractOptionalArg);
for(String alias : abstractOptionalArg.getAliases()) {
abbreviationMapBuilder.put(alias, abstractOptionalArg);
}
}
this.argumentAbbreviationMap = abbreviationMapBuilder.build();
}
private void validateVariantNumberOfRequiredParameters(@Nonnull ParseResult result) {
for(Int2ObjectMap.Entry<AbstractCommand> entry : this.variantCommands.int2ObjectEntrySet()) {
if (this.totalNumRequiredParameters == ((AbstractCommand)entry.getValue()).totalNumRequiredParameters) {
String var10001 = this.getFullyQualifiedName();
result.fail(Message.raw("Command '" + var10001 + "' and its variant '" + ((AbstractCommand)entry.getValue()).toString() + "' both have " + this.totalNumRequiredParameters + " required parameters. Variants must have different numbers of required parameters."));
return;
}
}
}
private void validateDefaultArguments(@Nonnull ParseResult parseResult) {
for(AbstractOptionalArg<?, ?> value : this.optionalArguments.values()) {
if (value instanceof DefaultArg<?> defaultArg) {
defaultArg.validateDefaultValue(parseResult);
}
}
}
public void requirePermission(@Nonnull String permission) {
this.permission = permission;
}
@Nullable
public String getFullyQualifiedName() {
if (this.parentCommand != null) {
if (this.isVariant()) {
return this.parentCommand.getFullyQualifiedName();
} else {
String var10000 = this.parentCommand.getFullyQualifiedName();
return var10000 + " " + this.name;
}
} else {
return this.name;
}
}
public int countParents() {
return this.parentCommand == null ? 0 : this.parentCommand.countParents() + 1;
}
public void addAliases(@Nonnull String... aliases) {
if (this.hasBeenRegistered) {
throw new IllegalStateException("Cannot add aliases when a command has already completed registration");
} else if (this.name == null) {
throw new IllegalStateException("Cannot add aliases to a command with no name");
} else {
for(String alias : aliases) {
this.aliases.add(alias.toLowerCase());
}
}
}
public void addSubCommand(@Nonnull AbstractCommand command) {
if (this.hasBeenRegistered) {
throw new IllegalStateException("Cannot add new subcommands when a command has already completed registration");
} else if (this.isVariant()) {
throw new IllegalStateException("Cannot add a subcommand to a variant command, can only add subcommands to named commands");
} else if (command.name == null) {
throw new IllegalArgumentException("Cannot add a subcommand with no name");
} else if (command.parentCommand != null) {
throw new IllegalArgumentException("Cannot re-use subcommands. Only one parent command allowed for each subcommand");
} else {
command.parentCommand = this;
if (this.subCommands.containsKey(command.name)) {
throw new IllegalArgumentException("Cannot have multiple subcommands with the same name");
} else if (this.subCommandsAliases.containsKey(command.name)) {
throw new IllegalArgumentException("Command has same name as existing command alias for command: " + command.name);
} else {
this.subCommands.put(command.name, command);
for(String alias : command.aliases) {
if (this.subCommandsAliases.containsKey(alias) || this.subCommands.containsKey(alias)) {
throw new IllegalArgumentException("Cannot specify a subcommand alias with the same name as an existing command or alias: " + alias);
}
this.subCommandsAliases.put(alias, command.name);
}
command.hasBeenRegistered = true;
}
}
}
public void addUsageVariant(@Nonnull AbstractCommand command) {
if (this.hasBeenRegistered) {
throw new IllegalStateException("Cannot add new variants when a command has already completed registration");
} else if (this.isVariant()) {
throw new IllegalStateException("Cannot add a command variant to a variant command, can only add variants to named commands");
} else if (command.name != null) {
throw new IllegalArgumentException("Cannot add a variant command with a name, use the description-only constructor");
} else if (command.parentCommand != null) {
throw new IllegalArgumentException("Cannot re-use variant commands. Only one parent command allowed for each variant command");
} else {
AbstractCommand variantWithSameNumRequiredParameters = (AbstractCommand)this.variantCommands.put(command.totalNumRequiredParameters, command);
if (variantWithSameNumRequiredParameters != null) {
int var10002 = command.totalNumRequiredParameters;
throw new IllegalArgumentException("You have already registered a variant command with " + var10002 + " required parameters. Command's class name: " + variantWithSameNumRequiredParameters.getClass().getName());
} else {
command.parentCommand = this;
command.hasBeenRegistered = true;
}
}
}
@Nullable
public CompletableFuture<Void> acceptCall(@Nonnull CommandSender sender, @Nonnull ParserContext parserContext, @Nonnull ParseResult parseResult) {
parserContext.convertToSubCommand();
return this.acceptCall0(sender, parserContext, parseResult);
}
@Nullable
private CompletableFuture<Void> acceptCall0(@Nonnull CommandSender sender, @Nonnull ParserContext parserContext, @Nonnull ParseResult parseResult) {
int numberOfPreOptionalTokens = parserContext.getNumPreOptionalTokens();
ObjectBooleanPair<CompletableFuture<Void>> completableFutureBooleanPair = this.checkForExecutingSubcommands(sender, parserContext, parseResult, numberOfPreOptionalTokens);
if (parseResult.failed()) {
return null;
} else if (completableFutureBooleanPair.rightBoolean()) {
return (CompletableFuture)completableFutureBooleanPair.left();
} else if (!this.hasPermission(sender)) {
parseResult.fail(MESSAGE_COMMANDS_PARSING_ERROR_NO_PERMISSION_FOR_COMMAND);
return null;
} else if (this instanceof AbstractCommandCollection && numberOfPreOptionalTokens != 0) {
HashSet<String> commandNames = new HashSet(this.subCommands.keySet());
commandNames.addAll(this.subCommandsAliases.keySet());
String firstToken = parserContext.getFirstToken();
String commandSuggestionPrefix = "\n/" + this.getFullyQualifiedName() + " ";
String suggestedCommands = commandSuggestionPrefix + String.join(commandSuggestionPrefix, StringUtil.sortByFuzzyDistance(firstToken, commandNames, 5));
parseResult.fail(Message.translation("server.commands.parsing.error.commandCollectionSubcommandNotFound").param("subcommand", firstToken).param("suggestions", suggestedCommands));
return null;
} else if (parserContext.isHelpSpecified()) {
sender.sendMessage(this.getUsageString(sender));
return null;
} else if (this.unavailableInSingleplayer && Constants.SINGLEPLAYER) {
parseResult.fail(MESSAGE_COMMAND_SINGLEPLAYER);
return null;
} else if (this.requiresConfirmation && !parserContext.isConfirmationSpecified()) {
parseResult.fail(MESSAGE_COMMANDS_PARSING_ERROR_ATTEMPTED_UNSAFE);
return null;
} else {
if (this.allowsExtraArguments) {
if (numberOfPreOptionalTokens < this.totalNumRequiredParameters) {
parseResult.fail(Message.translation("server.commands.parsing.error.wrongNumberRequiredParameters").param("expected", this.totalNumRequiredParameters).param("actual", numberOfPreOptionalTokens).insert("\n").insert(Message.translation("server.commands.help.usagecolon").param("usage", this.getUsageShort(sender, true))).insert("\n").insert(Message.translation("server.commands.help.useHelpToLearnMore").param("command", this.getFullyQualifiedName())));
return null;
}
} else if (this.totalNumRequiredParameters != numberOfPreOptionalTokens) {
parseResult.fail(Message.translation("server.commands.parsing.error.wrongNumberRequiredParameters").param("expected", this.totalNumRequiredParameters).param("actual", numberOfPreOptionalTokens).insert("\n").insert(Message.translation("server.commands.help.usagecolon").param("usage", this.getUsageShort(sender, true))).insert("\n").insert(Message.translation("server.commands.help.useHelpToLearnMore").param("command", this.getFullyQualifiedName())));
return null;
}
CommandContext commandContext = new CommandContext(this, sender, parserContext.getInputString());
this.processRequiredArguments(parserContext, parseResult, commandContext);
if (parseResult.failed()) {
return null;
} else {
this.processOptionalArguments(parserContext, parseResult, commandContext);
return parseResult.failed() ? null : this.execute(commandContext);
}
}
}
public boolean hasPermission(@Nonnull CommandSender sender) {
String permission = this.getPermission();
if (permission == null) {
return true;
} else if (sender.hasPermission(permission)) {
return this.parentCommand == null ? true : this.parentCommand.hasPermission(sender);
} else {
return false;
}
}
@Nonnull
private ObjectBooleanPair<CompletableFuture<Void>> checkForExecutingSubcommands(@Nonnull CommandSender sender, @Nonnull ParserContext parserContext, @Nonnull ParseResult parseResult, int numberOfPreOptionalTokens) {
if (parserContext.getNumPreOptSingleValueTokensBeforeListTokens() >= 0) {
if (!this.subCommands.isEmpty()) {
String subCommandName = parserContext.getPreOptionalSingleValueToken(0);
if (subCommandName != null) {
subCommandName = subCommandName.toLowerCase();
}
AbstractCommand subCommand = (AbstractCommand)this.subCommands.get(subCommandName);
if (subCommand != null) {
parserContext.convertToSubCommand();
return ObjectBooleanPair.<CompletableFuture<Void>>of(subCommand.acceptCall0(sender, parserContext, parseResult), true);
}
String alias = (String)this.subCommandsAliases.get(subCommandName);
if (alias != null) {
parserContext.convertToSubCommand();
return ObjectBooleanPair.<CompletableFuture<Void>>of(((AbstractCommand)this.subCommands.get(alias)).acceptCall0(sender, parserContext, parseResult), true);
}
}
AbstractCommand commandVariant = (AbstractCommand)this.variantCommands.get(numberOfPreOptionalTokens);
if (this.totalNumRequiredParameters != numberOfPreOptionalTokens && commandVariant != null) {
return ObjectBooleanPair.<CompletableFuture<Void>>of(commandVariant.acceptCall0(sender, parserContext, parseResult), true);
}
}
return ObjectBooleanPair.<CompletableFuture<Void>>of((Object)null, false);
}
private void processRequiredArguments(@Nonnull ParserContext parserContext, @Nonnull ParseResult parseResult, @Nonnull CommandContext commandContext) {
int currentReqArgIndex = 0;
for(RequiredArg<?> requiredArgument : this.requiredArguments) {
if (requiredArgument.getArgumentType().isListArgument() && parserContext.isListToken(currentReqArgIndex)) {
ParserContext.PreOptionalListContext preOptionalTokenContext = parserContext.getPreOptionalListToken(currentReqArgIndex);
++currentReqArgIndex;
commandContext.appendArgumentData(requiredArgument, preOptionalTokenContext.getTokens(), true, parseResult);
} else {
String[] argParameters = new String[requiredArgument.getArgumentType().getNumberOfParameters()];
for(int i = 0; i < requiredArgument.getArgumentType().getNumberOfParameters(); ++i) {
if (parserContext.isListToken(currentReqArgIndex)) {
parseResult.fail(Message.translation("server.commands.parsing.error.notAList").param("name", requiredArgument.getName()));
return;
}
argParameters[i] = parserContext.getPreOptionalSingleValueToken(currentReqArgIndex);
++currentReqArgIndex;
}
commandContext.appendArgumentData(requiredArgument, argParameters, false, parseResult);
if (parseResult.failed()) {
return;
}
}
}
}
private void processOptionalArguments(@Nonnull ParserContext parserContext, @Nonnull ParseResult parseResult, @Nonnull CommandContext commandContext) {
for(Map.Entry<String, List<List<String>>> optionalArgContext : parserContext.getOptionalArgs()) {
AbstractOptionalArg<? extends Argument<?, ?>, ?> optionalArg = this.argumentAbbreviationMap.get((String)optionalArgContext.getKey());
if (optionalArg == null) {
parseResult.fail(Message.translation("server.commands.parsing.error.couldNotFindOptionalArgName").param("input", (String)optionalArgContext.getKey()));
return;
}
if (optionalArg.getPermission() != null && !commandContext.sender().hasPermission(optionalArg.getPermission())) {
parseResult.fail(Message.translation("server.commands.parsing.error.noPermissionForOptional").param("argument", (String)optionalArgContext.getKey()));
return;
}
List<List<String>> optionalArgValues = (List)optionalArgContext.getValue();
if (optionalArg.getArgumentType().isListArgument() && optionalArgValues.size() > 1) {
String[] optionalArgParseValues = new String[optionalArgValues.size() * ((List)optionalArgValues.getFirst()).size()];
for(int i = 0; i < optionalArgValues.size(); ++i) {
List<String> values = (List)optionalArgValues.get(i);
for(int k = 0; k < values.size(); ++k) {
optionalArgParseValues[i * values.size() + k] = (String)values.get(k);
}
}
commandContext.appendArgumentData(optionalArg, optionalArgParseValues, true, parseResult);
} else {
commandContext.appendArgumentData(optionalArg, optionalArgValues.isEmpty() ? EMPTY_STRING_ARRAY : (String[])((List)optionalArgValues.getFirst()).toArray(EMPTY_STRING_ARRAY), false, parseResult);
}
}
for(AbstractOptionalArg<?, ?> optionalArg : this.optionalArguments.values()) {
optionalArg.verifyArgumentDependencies(commandContext, parseResult);
}
}
@Nullable
protected abstract CompletableFuture<Void> execute(@Nonnull CommandContext var1);
@Nonnull
public Message getUsageString(@Nonnull CommandSender sender) {
Message requiredArgsMessage = Message.raw("");
for(RequiredArg<?> requiredArgument : this.requiredArguments) {
requiredArgsMessage.insert(" ").insert(requiredArgument.getUsageMessageWithoutDescription());
if (requiredArgument.getArgumentType().isListArgument()) {
requiredArgsMessage.insert("/...");
}
}
Message requiresConfirmationMessage = this.requiresConfirmation ? MESSAGE_COMMANDS_PARSING_USAGE_REQUIRES_CONFIRMATION : Message.raw("");
Message requiredArgs = Message.raw("");
boolean requiredArgsShown = false;
for(RequiredArg<?> requiredArgument : this.requiredArguments) {
requiredArgsShown = true;
requiredArgs.insert("\n ").insert(requiredArgument.getUsageMessage());
}
Message optionalArgs = Message.raw("");
boolean optionalArgsShown = false;
Message defaultArgs = Message.raw("");
boolean defaultArgsShown = false;
Message flagArgs = Message.raw("");
boolean flagArgsShown = false;
for(Map.Entry<String, AbstractOptionalArg<?, ?>> entry : this.optionalArguments.entrySet()) {
AbstractOptionalArg<? extends Argument<?, ?>, ?> arg = (AbstractOptionalArg)entry.getValue();
if (arg.getPermission() == null || sender.hasPermission(arg.getPermission())) {
Objects.requireNonNull(arg);
byte var16 = 0;
switch (arg.typeSwitch<invokedynamic>(arg, var16)) {
case 0:
OptionalArg ignored = (OptionalArg)arg;
optionalArgsShown = true;
optionalArgs.insert("\n ").insert(arg.getUsageMessage());
break;
case 1:
DefaultArg ignored = (DefaultArg)arg;
defaultArgsShown = true;
defaultArgs.insert("\n ").insert(arg.getUsageMessage());
break;
case 2:
FlagArg ignored = (FlagArg)arg;
flagArgsShown = true;
flagArgs.insert("\n ").insert(arg.getUsageMessage());
}
}
}
if (requiredArgsShown) {
requiredArgs = Message.translation("server.commands.parsing.usage.requiredArgs").param("args", requiredArgs);
}
if (optionalArgsShown) {
optionalArgs = Message.translation("server.commands.parsing.usage.optionalArgs").param("args", optionalArgs);
}
if (flagArgsShown) {
flagArgs = Message.translation("server.commands.parsing.usage.flagArgs").param("args", flagArgs);
}
if (defaultArgsShown) {
defaultArgs = Message.translation("server.commands.parsing.usage.defaultArgs").param("args", defaultArgs);
}
Message variantsMessage = Message.raw("");
for(AbstractCommand value : this.variantCommands.values()) {
if (value.hasPermission(sender)) {
variantsMessage.insert(Message.translation("server.commands.parsing.usage.subcommands").param("separator", Message.translation("server.commands.parsing.usage.subcommandSeparator")).param("usage", value.getUsageString(sender)));
}
}
Message subcommandsMessage = Message.raw("");
for(AbstractCommand value : this.subCommands.values()) {
if (value.hasPermission(sender)) {
subcommandsMessage.insert(Message.translation("server.commands.parsing.usage.subcommands").param("separator", Message.translation("server.commands.parsing.usage.subcommandSeparator")).param("usage", value.getUsageString(sender)));
}
}
Message argTypesMessage = Message.raw("\nArgument Types:");
HashSet<ArgumentType<?>> allArgumentTypes = new HashSet();
for(RequiredArg<?> requiredArgument : this.requiredArguments) {
allArgumentTypes.add(requiredArgument.getArgumentType());
}
for(AbstractOptionalArg<?, ?> optionalArgument : this.optionalArguments.values()) {
allArgumentTypes.add(optionalArgument.getArgumentType());
}
for(ArgumentType<?> argumentType : allArgumentTypes) {
argTypesMessage.insert("\n ").insert(argumentType.getName()).insert(": ").insert(argumentType.getArgumentUsage()).insert("\n Examples: ").insert("'").insert(String.join("', '", argumentType.getExamples())).insert("'.");
}
return Message.translation("server.commands.parsing.usage.header").param("fullyQualifiedName", this.getFullyQualifiedName()).param("description", Message.translation(this.description)).param("listOfRequiredArgs", requiredArgsMessage).param("requiresConfirmation", requiresConfirmationMessage).param("requiredArgs", requiredArgs).param("optionalArgs", optionalArgs).param("defaultArgs", defaultArgs).param("flagArgs", flagArgs).param("argTypes", argTypesMessage).param("variants", variantsMessage).param("subcommands", subcommandsMessage);
}
@Nonnull
public Message getUsageShort(@Nonnull CommandSender sender, boolean fullyQualify) {
String indent = " ".repeat(this.countParents());
if (this.subCommands.isEmpty() && this.variantCommands.isEmpty()) {
String fullyQualifiedName = this.getFullyQualifiedName();
Message message = Message.raw(indent).insert(fullyQualify ? (fullyQualifiedName != null ? fullyQualifiedName : "???") : (this.name != null ? this.name : ""));
for(RequiredArg<?> requiredArgument : this.requiredArguments) {
message.insert(" ").insert(requiredArgument.getUsageOneLiner().color("#C1E0FF"));
}
for(AbstractOptionalArg<?, ?> optionalArgument : this.optionalArguments.values()) {
if (optionalArgument.hasPermission(sender)) {
message.insert(" ").insert(optionalArgument.getUsageOneLiner().color("#7E9EBC"));
}
}
return message;
} else {
String prefix = this.parentCommand == null ? "/" : indent;
Message message = Message.raw(prefix).insert(this.name);
boolean anyPermissible = false;
for(AbstractCommand variantCommand : this.variantCommands.values()) {
if (variantCommand.hasPermission(sender)) {
message.insert("\n ").insert(indent).insert(variantCommand.getUsageShort(sender, fullyQualify));
anyPermissible = true;
}
}
for(AbstractCommand subCommand : this.subCommands.values()) {
if (subCommand.hasPermission(sender)) {
message.insert("\n ").insert(indent).insert(subCommand.getUsageShort(sender, fullyQualify));
anyPermissible = true;
}
}
if (!anyPermissible) {
message.insert("\n ").insert(MESSAGE_COMMANDS_HELP_NO_PERMISSIBLE_SUB_COMMAND);
}
return message;
}
}
@Nonnull
private <R extends RequiredArg<D>, D> R registerRequiredArg(@Nonnull R requiredArgument) {
if (this.hasBeenRegistered) {
throw new IllegalStateException("Cannot add new arguments when a command has already completed registration");
} else if (requiredArgument.getCommandRegisteredTo().equals(this) && !this.requiredArguments.contains(requiredArgument)) {
this.totalNumRequiredParameters += requiredArgument.getArgumentType().getNumberOfParameters();
this.requiredArguments.add(requiredArgument);
return requiredArgument;
} else {
throw new IllegalArgumentException("Cannot re-use arguments");
}
}
@Nonnull
private <R extends AbstractOptionalArg<?, D>, D> R registerOptionalArg(@Nonnull R optionalArgument) {
if (this.hasBeenRegistered) {
throw new IllegalStateException("Cannot add new arguments when a command has already completed registration");
} else if (optionalArgument.getCommandRegisteredTo().equals(this) && !this.optionalArguments.containsKey(optionalArgument.getName().toLowerCase())) {
this.optionalArguments.put(optionalArgument.getName().toLowerCase(), optionalArgument);
return optionalArgument;
} else {
throw new IllegalArgumentException("Cannot re-use arguments");
}
}
@Nonnull
public <D> RequiredArg<D> withRequiredArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgumentType<D> argType) {
return this.registerRequiredArg(new RequiredArg(this, name, description, argType));
}
public <W extends WrappedArg<D>, D> W withRequiredArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgWrapper<W, D> wrapper) {
return wrapper.wrapArg(this.registerRequiredArg(new RequiredArg(this, name, description, wrapper.argumentType())));
}
@Nonnull
public <D> RequiredArg<List<D>> withListRequiredArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgumentType<D> argType) {
return this.registerRequiredArg(new RequiredArg(this, name, description, new ListArgumentType(argType)));
}
@Nonnull
public <D> DefaultArg<D> withDefaultArg(String name, String description, ArgumentType<D> argType, @Nullable D defaultValue, String defaultValueDescription) {
return (DefaultArg)this.registerOptionalArg(new DefaultArg(this, name, description, argType, defaultValue, defaultValueDescription));
}
public <W extends WrappedArg<D>, D> W withDefaultArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgWrapper<W, D> wrapper, D defaultValue, @Nonnull String defaultValueDescription) {
return wrapper.wrapArg(this.registerOptionalArg(new DefaultArg(this, name, description, wrapper.argumentType(), defaultValue, defaultValueDescription)));
}
@Nonnull
public <D> DefaultArg<List<D>> withListDefaultArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgumentType<D> argType, List<D> defaultValue, @Nonnull String defaultValueDescription) {
return (DefaultArg)this.registerOptionalArg(new DefaultArg(this, name, description, new ListArgumentType(argType), defaultValue, defaultValueDescription));
}
@Nonnull
public <D> OptionalArg<D> withOptionalArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgumentType<D> argType) {
return (OptionalArg)this.registerOptionalArg(new OptionalArg(this, name, description, argType));
}
public <W extends WrappedArg<D>, D> W withOptionalArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgWrapper<W, D> wrapper) {
return wrapper.wrapArg(this.registerOptionalArg(new OptionalArg(this, name, description, wrapper.argumentType())));
}
@Nonnull
public <D> OptionalArg<List<D>> withListOptionalArg(@Nonnull String name, @Nonnull String description, @Nonnull ArgumentType<D> argType) {
return (OptionalArg)this.registerOptionalArg(new OptionalArg(this, name, description, new ListArgumentType(argType)));
}
@Nonnull
public FlagArg withFlagArg(@Nonnull String name, @Nonnull String description) {
return (FlagArg)this.registerOptionalArg(new FlagArg(this, name, description));
}
public boolean isVariant() {
return this.name == null;
}
@Nullable
public String getName() {
return this.name;
}
@Nonnull
public Set<String> getAliases() {
return this.aliases;
}
public String getDescription() {
return this.description;
}
@Nullable
public CommandOwner getOwner() {
return this.owner;
}
@Nullable
public String getPermission() {
return this.permission;
}
@Nonnull
public Map<String, AbstractCommand> getSubCommands() {
return this.subCommands;
}
@Nonnull
public List<RequiredArg<?>> getRequiredArguments() {
return this.requiredArguments;
}
public boolean hasBeenRegistered() {
return this.hasBeenRegistered;
}
}