mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-25 18:09:17 +00:00
Add Leaf Commands (WIP)
* Added Leaf Commands base * Added WIP /leaf reload * Added /leaf version * Change /gale permission to OP as default
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
package org.dreeam.leaf.command;
|
||||
|
||||
import io.papermc.paper.command.CommandUtil;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minecraft.Util;
|
||||
import org.dreeam.leaf.command.subcommands.ReloadCommand;
|
||||
import org.dreeam.leaf.command.subcommands.VersionCommand;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class LeafCommand extends Command {
|
||||
|
||||
public static final String COMMAND_LABEL = "leaf";
|
||||
public static final String BASE_PERM = LeafCommands.COMMAND_BASE_PERM + "." + COMMAND_LABEL;
|
||||
private static final Permission basePermission = new Permission(BASE_PERM, PermissionDefault.OP);
|
||||
// subcommand label -> subcommand
|
||||
private static final LeafSubcommand RELOAD_SUBCOMMAND = new ReloadCommand();
|
||||
private static final LeafSubcommand VERSION_SUBCOMMAND = new VersionCommand();
|
||||
private static final Map<String, LeafSubcommand> SUBCOMMANDS = Util.make(() -> {
|
||||
final Map<Set<String>, LeafSubcommand> commands = new HashMap<>();
|
||||
|
||||
commands.put(Set.of(ReloadCommand.LITERAL_ARGUMENT), RELOAD_SUBCOMMAND);
|
||||
commands.put(Set.of(VersionCommand.LITERAL_ARGUMENT), VERSION_SUBCOMMAND);
|
||||
|
||||
return commands.entrySet().stream()
|
||||
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
});
|
||||
// alias -> subcommand label
|
||||
private static final Map<String, String> ALIASES = Util.make(() -> {
|
||||
final Map<String, Set<String>> aliases = new HashMap<>();
|
||||
|
||||
aliases.put(VersionCommand.LITERAL_ARGUMENT, Set.of("ver"));
|
||||
|
||||
return aliases.entrySet().stream()
|
||||
.flatMap(entry -> entry.getValue().stream().map(s -> Map.entry(s, entry.getKey())))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
});
|
||||
|
||||
private String createUsageMessage(Collection<String> arguments) {
|
||||
return "/" + COMMAND_LABEL + " [" + String.join(" | ", arguments) + "]";
|
||||
}
|
||||
|
||||
public LeafCommand() {
|
||||
super(COMMAND_LABEL);
|
||||
this.description = "Leaf related commands";
|
||||
this.usageMessage = this.createUsageMessage(SUBCOMMANDS.keySet());
|
||||
final List<Permission> permissions = SUBCOMMANDS.values().stream().map(LeafSubcommand::getPermission).filter(Objects::nonNull).toList();
|
||||
this.setPermission(BASE_PERM);
|
||||
final PluginManager pluginManager = Bukkit.getServer().getPluginManager();
|
||||
pluginManager.addPermission(basePermission);
|
||||
for (final Permission permission : permissions) {
|
||||
pluginManager.addPermission(permission);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> tabComplete(
|
||||
final @NotNull CommandSender sender,
|
||||
final @NotNull String alias,
|
||||
final String[] args,
|
||||
final @Nullable Location location
|
||||
) throws IllegalArgumentException {
|
||||
if (args.length <= 1) {
|
||||
List<String> subCommandArguments = new ArrayList<>(SUBCOMMANDS.size());
|
||||
|
||||
for (Map.Entry<String, LeafSubcommand> subCommandEntry : SUBCOMMANDS.entrySet()) {
|
||||
if (subCommandEntry.getValue().testPermission(sender)) {
|
||||
subCommandArguments.add(subCommandEntry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return CommandUtil.getListMatchingLast(sender, args, subCommandArguments);
|
||||
}
|
||||
|
||||
final @Nullable Pair<String, LeafSubcommand> subCommand = resolveCommand(args[0]);
|
||||
|
||||
if (subCommand != null && subCommand.second().testPermission(sender)) {
|
||||
return subCommand.second().tabComplete(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length));
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private boolean testHasOnePermission(CommandSender sender) {
|
||||
for (Map.Entry<String, LeafSubcommand> subCommandEntry : SUBCOMMANDS.entrySet()) {
|
||||
if (subCommandEntry.getValue().testPermission(sender)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(
|
||||
final CommandSender sender,
|
||||
final @NotNull String commandLabel,
|
||||
final String[] args
|
||||
) {
|
||||
// Check if the sender has the base permission and at least one specific permission
|
||||
if (!sender.hasPermission(basePermission) || !this.testHasOnePermission(sender)) {
|
||||
sender.sendMessage(Bukkit.permissionMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine the usage message with the subcommands they can perform
|
||||
List<String> subCommandArguments = new ArrayList<>(SUBCOMMANDS.size());
|
||||
for (Map.Entry<String, LeafSubcommand> subCommandEntry : SUBCOMMANDS.entrySet()) {
|
||||
if (subCommandEntry.getValue().testPermission(sender)) {
|
||||
subCommandArguments.add(subCommandEntry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
String specificUsageMessage = this.createUsageMessage(subCommandArguments);
|
||||
|
||||
// If they did not give a subcommand
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage(Component.text("Command usage: " + specificUsageMessage, NamedTextColor.GRAY));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If they do not have permission for the subcommand they gave, or the argument is not a valid subcommand
|
||||
final @Nullable Pair<String, LeafSubcommand> subCommand = resolveCommand(args[0]);
|
||||
if (subCommand == null || !subCommand.second().testPermission(sender)) {
|
||||
sender.sendMessage(Component.text("Usage: " + specificUsageMessage, NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Execute the subcommand
|
||||
final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
return subCommand.second().execute(sender, subCommand.first(), choppedArgs);
|
||||
|
||||
}
|
||||
|
||||
private static @Nullable Pair<String, LeafSubcommand> resolveCommand(String label) {
|
||||
label = label.toLowerCase(Locale.ENGLISH);
|
||||
@Nullable LeafSubcommand subCommand = SUBCOMMANDS.get(label);
|
||||
if (subCommand == null) {
|
||||
final @Nullable String command = ALIASES.get(label);
|
||||
if (command != null) {
|
||||
label = command;
|
||||
subCommand = SUBCOMMANDS.get(command);
|
||||
}
|
||||
}
|
||||
|
||||
if (subCommand != null) {
|
||||
return Pair.of(label, subCommand);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.dreeam.leaf.command;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public final class LeafCommands {
|
||||
|
||||
public static final String COMMAND_BASE_PERM = CraftDefaultPermissions.LEAF_ROOT + ".command";
|
||||
|
||||
private LeafCommands() {
|
||||
}
|
||||
|
||||
private static final Map<String, Command> COMMANDS = new HashMap<>();
|
||||
|
||||
static {
|
||||
COMMANDS.put(LeafCommand.COMMAND_LABEL, new LeafCommand());
|
||||
}
|
||||
|
||||
public static void registerCommands(final MinecraftServer server) {
|
||||
COMMANDS.forEach((s, command) -> server.server.getCommandMap().register(s, "Leaf", command));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.dreeam.leaf.command;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.Permission;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public interface LeafSubcommand {
|
||||
|
||||
boolean execute(CommandSender sender, String subCommand, String[] args);
|
||||
|
||||
default List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
boolean testPermission(CommandSender sender);
|
||||
|
||||
@Nullable Permission getPermission();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.dreeam.leaf.command;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
public abstract class PermissionedLeafSubcommand implements LeafSubcommand {
|
||||
|
||||
public final Permission permission;
|
||||
|
||||
protected PermissionedLeafSubcommand(Permission permission) {
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
protected PermissionedLeafSubcommand(String permission, PermissionDefault permissionDefault) {
|
||||
this(new Permission(permission, permissionDefault));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(@NotNull CommandSender sender) {
|
||||
return sender.hasPermission(this.permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Permission getPermission() {
|
||||
return this.permission;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.dreeam.leaf.command.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
import org.dreeam.leaf.command.LeafCommand;
|
||||
import org.dreeam.leaf.command.PermissionedLeafSubcommand;
|
||||
import org.dreeam.leaf.config.LeafConfig;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public final class ReloadCommand extends PermissionedLeafSubcommand {
|
||||
|
||||
public final static String LITERAL_ARGUMENT = "reload";
|
||||
public static final String PERM = LeafCommand.BASE_PERM + "." + LITERAL_ARGUMENT;
|
||||
|
||||
public ReloadCommand() {
|
||||
super(PERM, PermissionDefault.OP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
this.doReload(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doReload(final CommandSender sender) {
|
||||
Command.broadcastCommandMessage(sender, Component.text("Reloading Leaf config...", NamedTextColor.GREEN));
|
||||
|
||||
LeafConfig.reloadAsync(sender);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.dreeam.leaf.command.subcommands;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
import org.dreeam.leaf.command.LeafCommand;
|
||||
import org.dreeam.leaf.command.PermissionedLeafSubcommand;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public final class VersionCommand extends PermissionedLeafSubcommand {
|
||||
|
||||
public final static String LITERAL_ARGUMENT = "version";
|
||||
public static final String PERM = LeafCommand.BASE_PERM + "." + LITERAL_ARGUMENT;
|
||||
|
||||
public VersionCommand() {
|
||||
super(PERM, PermissionDefault.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version");
|
||||
|
||||
if (ver != null) {
|
||||
ver.execute(sender, LeafCommand.COMMAND_LABEL, me.titaniumtown.ArrayConstants.emptyStringArray); // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandSender sender) {
|
||||
return super.testPermission(sender) && sender.hasPermission("bukkit.command.version");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user