mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-02-05 23:11:56 +01:00
CommandWithSubcommands
This commit is contained in:
parent
ba96fc3d90
commit
a3015db57c
@ -27,6 +27,19 @@ public interface CMDSender {
|
||||
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
default boolean hasAllPermissionsFor(Subcommand subcommand) {
|
||||
return !isMissingPermissionsFor(subcommand);
|
||||
}
|
||||
|
||||
default boolean isMissingPermissionsFor(Subcommand subcommand) {
|
||||
for (String permission : subcommand.getRequiredPermissions()) {
|
||||
if (!hasPermission(permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<UUID> getUUID();
|
||||
|
||||
void send(String message);
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import com.djrapitops.plan.commands.Arguments;
|
||||
import com.djrapitops.plugin.command.ColorScheme;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommandWithSubcommands extends Subcommand {
|
||||
|
||||
private final List<Subcommand> subcommands;
|
||||
private BiConsumer<CMDSender, Arguments> fallback;
|
||||
|
||||
private CommandWithSubcommands() {
|
||||
subcommands = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public void onHelp(CMDSender sender, Arguments arguments) {
|
||||
MessageBuilder message = sender.buildMessage()
|
||||
.addPart("Header").newLine().newLine();
|
||||
new HelpFormatter(/* TODO */new ColorScheme("§2", "§7", "§f"), getPrimaryAlias(),
|
||||
subcommands.stream().filter(sender::hasAllPermissionsFor).collect(Collectors.toList()))
|
||||
.addSubcommands(message);
|
||||
|
||||
message.newLine().addPart("Footer")
|
||||
.send();
|
||||
}
|
||||
|
||||
public void onCommand(CMDSender sender, Arguments arguments) {
|
||||
if (sender.isMissingPermissionsFor(this)) {
|
||||
sender.send(/* TODO */"NO PERMISSION");
|
||||
return;
|
||||
}
|
||||
Optional<String> gotAlias = arguments.get(0);
|
||||
if (gotAlias.isPresent()) {
|
||||
String alias = gotAlias.get();
|
||||
if ("help".equals(alias)) {
|
||||
onHelp(sender, arguments);
|
||||
} else {
|
||||
for (Subcommand subcommand : subcommands) {
|
||||
if (subcommand.getAliases().contains(alias)) {
|
||||
if (sender.isMissingPermissionsFor(subcommand)) {
|
||||
sender.send(/* TODO */"NO PERMISSION");
|
||||
continue;
|
||||
}
|
||||
subcommand.getExecutor().accept(sender, arguments.removeFirst());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Use fallback if no command is found.
|
||||
fallback.accept(sender, arguments);
|
||||
}
|
||||
|
||||
public List<String> onTabComplete(CMDSender sender, Arguments arguments) {
|
||||
Optional<String> gotAlias = arguments.get(0);
|
||||
List<String> options = new ArrayList<>();
|
||||
if (gotAlias.isPresent()) {
|
||||
for (Subcommand subcommand : subcommands) {
|
||||
if (sender.isMissingPermissionsFor(subcommand)) {
|
||||
continue;
|
||||
}
|
||||
for (String alias : subcommand.getAliases()) {
|
||||
if (alias.startsWith(gotAlias.get())) {
|
||||
options.add(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Subcommand subcommand : subcommands) {
|
||||
options.add(subcommand.getPrimaryAlias());
|
||||
}
|
||||
}
|
||||
Collections.sort(options);
|
||||
return options;
|
||||
}
|
||||
|
||||
public static class Builder extends Subcommand.Builder {
|
||||
private final CommandWithSubcommands command;
|
||||
|
||||
private Builder() {
|
||||
this(new CommandWithSubcommands());
|
||||
}
|
||||
|
||||
private Builder(CommandWithSubcommands command) {
|
||||
super(command);
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public Builder subcommand(Subcommand subcommand) {
|
||||
command.subcommands.add(subcommand);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fallback(BiConsumer<CMDSender, Arguments> executor) {
|
||||
command.fallback = executor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fallbackOrHelpFallback(
|
||||
BiPredicate<CMDSender, Arguments> canBeUsed,
|
||||
BiConsumer<CMDSender, Arguments> executor
|
||||
) {
|
||||
return fallback((sender, arguments) -> {
|
||||
if (canBeUsed.test(sender, arguments)) {
|
||||
executor.accept(sender, arguments);
|
||||
} else {
|
||||
command.onHelp(sender, arguments);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CommandWithSubcommands build() {
|
||||
super.build();
|
||||
if (command.fallback == null) fallback(command::onHelp);
|
||||
onCommand(command::onCommand);
|
||||
onTabComplete(command::onTabComplete);
|
||||
return command;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import com.djrapitops.plugin.command.ColorScheme;
|
||||
import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class HelpFormatter {
|
||||
|
||||
private final ColorScheme colors;
|
||||
private final String mainCommand;
|
||||
private final List<Subcommand> subcommands;
|
||||
|
||||
public HelpFormatter(
|
||||
ColorScheme colors, String mainCommand, List<Subcommand> subcommands
|
||||
) {
|
||||
this.colors = colors;
|
||||
this.mainCommand = mainCommand;
|
||||
this.subcommands = subcommands;
|
||||
}
|
||||
|
||||
public MessageBuilder addSubcommands(MessageBuilder message) {
|
||||
for (Subcommand subcommand : subcommands) {
|
||||
String alias = subcommand.getPrimaryAlias();
|
||||
message.addPart(colors.getMainColor() + mainCommand + " " + alias + "---")
|
||||
.hover(argumentsAndAliases(subcommand.getArguments(), subcommand.getAliases()));
|
||||
message.addPart(colors.getSecondaryColor() + subcommand.getDescription())
|
||||
.hover(subcommand.getInDepthDescription());
|
||||
message.tabular("---");
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private List<String> argumentsAndAliases(List<Subcommand.ArgumentDescriptor> descriptors, Set<String> aliases) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
lines.add(colors.getTertiaryColor() + "Arguments:");
|
||||
for (Subcommand.ArgumentDescriptor descriptor : descriptors) {
|
||||
if (descriptor.isRequired()) {
|
||||
lines.add(" " + colors.getMainColor() + "§l<" + descriptor.getName() + ">§r " + colors.getSecondaryColor() + descriptor.getDescription());
|
||||
} else {
|
||||
lines.add(" " + colors.getMainColor() + "[" + descriptor.getName() + "] " + colors.getSecondaryColor() + descriptor.getDescription());
|
||||
}
|
||||
}
|
||||
lines.add(colors.getTertiaryColor() + "Aliases:" + new TextStringBuilder().appendWithSeparators(aliases, " | ").toString());
|
||||
return lines;
|
||||
}
|
||||
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -23,7 +24,9 @@ public interface MessageBuilder {
|
||||
|
||||
MessageBuilder defineColorCharacter(char colorChar);
|
||||
|
||||
MessageBuilder append(String msg);
|
||||
MessageBuilder addPart(String msg);
|
||||
|
||||
MessageBuilder newLine();
|
||||
|
||||
MessageBuilder link(String address);
|
||||
|
||||
@ -33,6 +36,8 @@ public interface MessageBuilder {
|
||||
|
||||
MessageBuilder hover(String... text);
|
||||
|
||||
MessageBuilder hover(Collection<String> text);
|
||||
|
||||
MessageBuilder indent(int spaces);
|
||||
|
||||
MessageBuilder tabular(CharSequence columnSeparator);
|
||||
|
@ -27,15 +27,17 @@ public class Subcommand {
|
||||
private final Set<String> aliases;
|
||||
private final Set<String> requiredPermissions;
|
||||
private final List<String> inDepthDescription;
|
||||
private final List<ArgumentDescriptor> arguments;
|
||||
private String primaryAlias;
|
||||
private String description;
|
||||
private BiConsumer<CMDSender, Arguments> executor;
|
||||
private BiFunction<CMDSender, Arguments, List<String>> argumentResolver;
|
||||
|
||||
private Subcommand() {
|
||||
Subcommand() {
|
||||
aliases = new HashSet<>();
|
||||
requiredPermissions = new HashSet<>();
|
||||
inDepthDescription = new ArrayList<>();
|
||||
arguments = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static SubcommandBuilder builder() {
|
||||
@ -62,6 +64,10 @@ public class Subcommand {
|
||||
return inDepthDescription;
|
||||
}
|
||||
|
||||
public List<ArgumentDescriptor> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public BiConsumer<CMDSender, Arguments> getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
@ -71,9 +77,15 @@ public class Subcommand {
|
||||
}
|
||||
|
||||
public static class Builder implements SubcommandBuilder {
|
||||
private Subcommand subcommand;
|
||||
private final Subcommand subcommand;
|
||||
|
||||
private Builder() {}
|
||||
private Builder() {
|
||||
this.subcommand = new Subcommand();
|
||||
}
|
||||
|
||||
Builder(Subcommand subcommand) {
|
||||
this.subcommand = subcommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubcommandBuilder alias(String alias) {
|
||||
@ -108,6 +120,18 @@ public class Subcommand {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubcommandBuilder requiredArgument(String name, String description) {
|
||||
subcommand.arguments.add(new ArgumentDescriptor(name, description, true));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubcommandBuilder optionalArgument(String name, String description) {
|
||||
subcommand.arguments.add(new ArgumentDescriptor(name, description, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubcommandBuilder onCommand(BiConsumer<CMDSender, Arguments> executor) {
|
||||
subcommand.executor = executor;
|
||||
@ -130,4 +154,27 @@ public class Subcommand {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArgumentDescriptor {
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final boolean required;
|
||||
|
||||
public ArgumentDescriptor(String name, String description, boolean required) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,10 @@ public interface SubcommandBuilder {
|
||||
|
||||
SubcommandBuilder inDepthDescription(String... lines);
|
||||
|
||||
SubcommandBuilder requiredArgument(String name, String description);
|
||||
|
||||
SubcommandBuilder optionalArgument(String name, String description);
|
||||
|
||||
SubcommandBuilder onCommand(BiConsumer<CMDSender, Arguments> executor);
|
||||
|
||||
SubcommandBuilder onTabComplete(BiFunction<CMDSender, Arguments, List<String>> resolver);
|
||||
|
Loading…
Reference in New Issue
Block a user