mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-30 20:39:15 +00:00
feat: finish perms system, fix bugs
This commit is contained in:
@@ -6,6 +6,7 @@ import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.configuration.MemorySection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
@@ -30,7 +31,6 @@ import org.leavesmc.leaves.config.api.impl.ConfigValidatorImpl.IntConfigValidato
|
||||
import org.leavesmc.leaves.config.api.impl.ConfigValidatorImpl.ListConfigValidator;
|
||||
import org.leavesmc.leaves.config.api.impl.ConfigValidatorImpl.LongConfigValidator;
|
||||
import org.leavesmc.leaves.config.api.impl.ConfigValidatorImpl.StringConfigValidator;
|
||||
import org.leavesmc.leaves.neo_command.LeavesCommands;
|
||||
import org.leavesmc.leaves.profile.LeavesMinecraftSessionService;
|
||||
import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule;
|
||||
import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules;
|
||||
@@ -95,7 +95,7 @@ public final class LeavesConfig {
|
||||
GlobalConfigManager.init();
|
||||
|
||||
registerCommand("leaves", new LeavesCommand());
|
||||
LeavesCommands.registerLeavesCommands();
|
||||
org.leavesmc.leaves.neo_command.leaves.LeavesCommand.INSTANCE.register();
|
||||
}
|
||||
|
||||
public static void reload() {
|
||||
@@ -152,9 +152,16 @@ public final class LeavesConfig {
|
||||
public void verify(Boolean old, Boolean value) throws IllegalArgumentException {
|
||||
if (value) {
|
||||
registerCommand("bot", new BotCommand());
|
||||
org.leavesmc.leaves.neo_command.bot.BotCommand.INSTANCE.register();
|
||||
Actions.registerAll();
|
||||
} else {
|
||||
unregisterCommand("bot");
|
||||
org.leavesmc.leaves.neo_command.bot.BotCommand.INSTANCE.unregister();
|
||||
}
|
||||
if (old != null && !old.equals(value)) {
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(org.leavesmc.leaves.neo_command.bot.BotCommand::hasPermission)
|
||||
.forEach(org.bukkit.entity.Player::updateCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,15 +197,58 @@ public final class LeavesConfig {
|
||||
@GlobalConfig("open-fakeplayer-inventory")
|
||||
public boolean canOpenInventory = false;
|
||||
|
||||
@GlobalConfig("use-action")
|
||||
@GlobalConfig(value = "use-action", validator = CanUseActionValidator.class)
|
||||
public boolean canUseAction = true;
|
||||
|
||||
@GlobalConfig("modify-config")
|
||||
private static class CanUseActionValidator extends BooleanConfigValidator {
|
||||
@Override
|
||||
public void verify(Boolean old, Boolean value) throws IllegalArgumentException {
|
||||
if (old != null && !old.equals(value)) {
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(sender ->
|
||||
org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender)
|
||||
|| org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender, "action")
|
||||
)
|
||||
.forEach(org.bukkit.entity.Player::updateCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GlobalConfig(value = "modify-config", validator = CanModifyConfigValidator.class)
|
||||
public boolean canModifyConfig = false;
|
||||
|
||||
@GlobalConfig("manual-save-and-load")
|
||||
private static class CanModifyConfigValidator extends BooleanConfigValidator {
|
||||
@Override
|
||||
public void verify(Boolean old, Boolean value) throws IllegalArgumentException {
|
||||
if (old != null && !old.equals(value)) {
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(sender ->
|
||||
org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender)
|
||||
|| org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender, "config")
|
||||
)
|
||||
.forEach(org.bukkit.entity.Player::updateCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GlobalConfig(value = "manual-save-and-load", validator = CanManualSaveAndLoadValidator.class)
|
||||
public boolean canManualSaveAndLoad = false;
|
||||
|
||||
private static class CanManualSaveAndLoadValidator extends BooleanConfigValidator {
|
||||
@Override
|
||||
public void verify(Boolean old, Boolean value) throws IllegalArgumentException {
|
||||
if (old != null && !old.equals(value)) {
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(sender ->
|
||||
org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender)
|
||||
|| org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender, "save")
|
||||
|| org.leavesmc.leaves.neo_command.bot.BotCommand.hasPermission(sender, "load")
|
||||
)
|
||||
.forEach(org.bukkit.entity.Player::updateCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GlobalConfig(value = "cache-skin", lock = true)
|
||||
public boolean useSkinCache = false;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static org.leavesmc.leaves.neo_command.leaves.ArgumentSuggestions.strings;
|
||||
import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings;
|
||||
|
||||
public class ServerMoveAction extends ServerStateBotAction<ServerMoveAction> {
|
||||
private static final Map<String, MoveDirection> NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap(
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.leavesmc.leaves.neo_command.CommandContext;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static org.leavesmc.leaves.neo_command.leaves.ArgumentSuggestions.strings;
|
||||
import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings;
|
||||
|
||||
public abstract class ServerTimerBotAction<E extends ServerTimerBotAction<E>> extends ServerBotAction<E> {
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class ArgumentNode<T> extends CommandNode {
|
||||
@@ -36,4 +39,24 @@ public abstract class ArgumentNode<T> extends CommandNode {
|
||||
|
||||
return argumentBuilder;
|
||||
}
|
||||
|
||||
public static class ArgumentSuggestions {
|
||||
@Contract(pure = true)
|
||||
public static WrappedArgument.@NotNull SuggestionApplier strings(String... values) {
|
||||
return (context, builder) -> {
|
||||
for (String s : values) {
|
||||
builder.suggest(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static WrappedArgument.@NotNull SuggestionApplier strings(List<String> values) {
|
||||
return (context, builder) -> {
|
||||
for (String s : values) {
|
||||
builder.suggest(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,14 @@ public abstract class CommandNode {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean requires(CommandSourceStack source) {
|
||||
public boolean requires(CommandSourceStack source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
|
||||
ArgumentBuilder<CommandSourceStack, ?> builder = compileBase();
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package org.leavesmc.leaves.neo_command;
|
||||
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandUtils {
|
||||
|
||||
public static void registerPermissions(@NotNull List<String> permissions) {
|
||||
PluginManager pluginManager = Bukkit.getServer().getPluginManager();
|
||||
for (String perm : permissions) {
|
||||
if (pluginManager.getPermission(perm) == null) {
|
||||
pluginManager.addPermission(new Permission(perm, PermissionDefault.OP));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public static @NotNull List<String> getListClosestMatchingLast(
|
||||
final String last,
|
||||
final Collection<?> collection
|
||||
) {
|
||||
if (collection.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
ArrayList<Candidate> candidates = Lists.newArrayList();
|
||||
String lastLower = last.toLowerCase();
|
||||
for (String item : Iterables.transform(collection, Functions.toStringFunction())) {
|
||||
String itemLower = item.toLowerCase();
|
||||
if (itemLower.startsWith(lastLower)) {
|
||||
candidates.add(Candidate.of(item, 0));
|
||||
} else if (itemLower.contains(lastLower)) {
|
||||
candidates.add(Candidate.of(item, damerauLevenshteinDistance(lastLower, itemLower)));
|
||||
}
|
||||
}
|
||||
candidates.sort(Comparator.comparingInt(c -> c.score));
|
||||
|
||||
List<String> results = new ArrayList<>(candidates.size());
|
||||
for (Candidate candidate : candidates) {
|
||||
results.add(candidate.item);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the Dameraur-Levenshtein Distance between two strings. Adapted
|
||||
* from the algorithm at <a href="http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance">Wikipedia: Damerau–Levenshtein distance</a>
|
||||
*
|
||||
* @param s1 The first string being compared.
|
||||
* @param s2 The second string being compared.
|
||||
* @return The number of substitutions, deletions, insertions, and
|
||||
* transpositions required to get from s1 to s2.
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static int damerauLevenshteinDistance(@Nullable String s1, @Nullable String s2) {
|
||||
if (s1 == null && s2 == null) {
|
||||
return 0;
|
||||
}
|
||||
if (s1 != null && s2 == null) {
|
||||
return s1.length();
|
||||
}
|
||||
if (s1 == null) {
|
||||
return s2.length();
|
||||
}
|
||||
|
||||
int s1Len = s1.length();
|
||||
int s2Len = s2.length();
|
||||
int[][] H = new int[s1Len + 2][s2Len + 2];
|
||||
|
||||
int INF = s1Len + s2Len;
|
||||
H[0][0] = INF;
|
||||
for (int i = 0; i <= s1Len; i++) {
|
||||
H[i + 1][1] = i;
|
||||
H[i + 1][0] = INF;
|
||||
}
|
||||
for (int j = 0; j <= s2Len; j++) {
|
||||
H[1][j + 1] = j;
|
||||
H[0][j + 1] = INF;
|
||||
}
|
||||
|
||||
Map<Character, Integer> sd = new HashMap<>();
|
||||
for (char Letter : (s1 + s2).toCharArray()) {
|
||||
if (!sd.containsKey(Letter)) {
|
||||
sd.put(Letter, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i <= s1Len; i++) {
|
||||
int DB = 0;
|
||||
for (int j = 1; j <= s2Len; j++) {
|
||||
int i1 = sd.get(s2.charAt(j - 1));
|
||||
int j1 = DB;
|
||||
|
||||
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
|
||||
H[i + 1][j + 1] = H[i][j];
|
||||
DB = j;
|
||||
} else {
|
||||
H[i + 1][j + 1] = Math.min(H[i][j], Math.min(H[i + 1][j], H[i][j + 1])) + 1;
|
||||
}
|
||||
|
||||
H[i + 1][j + 1] = Math.min(H[i + 1][j + 1], H[i1][j1] + (i - i1 - 1) + 1 + (j - j1 - 1));
|
||||
}
|
||||
sd.put(s1.charAt(i - 1), i);
|
||||
}
|
||||
|
||||
return H[s1Len + 1][s2Len + 1];
|
||||
}
|
||||
|
||||
// Copy from org/bukkit/command/defaults/HelpCommand.java
|
||||
private record Candidate(String item, int score) {
|
||||
@Contract("_, _ -> new")
|
||||
private static @NotNull Candidate of(String item, int score) {
|
||||
return new Candidate(item, score);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.leavesmc.leaves.neo_command;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotCommand;
|
||||
import org.leavesmc.leaves.neo_command.leaves.LeavesCommand;
|
||||
|
||||
public class LeavesCommands {
|
||||
public static void registerLeavesCommands() {
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = MinecraftServer.getServer().getCommands().getDispatcher();
|
||||
new LeavesCommand().register(dispatcher);
|
||||
new BotCommand().register(dispatcher);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class LiteralNode extends CommandNode {
|
||||
|
||||
@@ -19,7 +19,17 @@ public class LiteralNode extends CommandNode {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void register(@NotNull CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
dispatcher.register((LiteralArgumentBuilder<CommandSourceStack>) compile());
|
||||
public void register() {
|
||||
MinecraftServer.getServer()
|
||||
.getCommands()
|
||||
.getDispatcher()
|
||||
.register((LiteralArgumentBuilder<CommandSourceStack>) compile());
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = MinecraftServer.getServer()
|
||||
.getCommands()
|
||||
.getDispatcher();
|
||||
dispatcher.getRoot().removeCommand(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class BotArgument implements CustomArgumentType<ServerBot, String> {
|
||||
@Override
|
||||
public ArgumentType<String> getBaseArgumentType() {
|
||||
return StringArgumentType.string();
|
||||
return StringArgumentType.word();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,33 +1,57 @@
|
||||
package org.leavesmc.leaves.neo_command.bot;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.LeavesConfig;
|
||||
import org.leavesmc.leaves.neo_command.CommandNode;
|
||||
import org.leavesmc.leaves.neo_command.CommandUtils;
|
||||
import org.leavesmc.leaves.neo_command.LiteralNode;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.ConfigCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.CreateCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.ListCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.LoadCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.SaveCommand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BotCommand extends LiteralNode {
|
||||
public static final BotCommand INSTANCE = new BotCommand();
|
||||
private static final String PERM_BASE = "bukkit.command.bot";
|
||||
|
||||
public BotCommand() {
|
||||
private BotCommand() {
|
||||
super("bot_neo");
|
||||
this.children(
|
||||
ActionCommand::new,
|
||||
ListCommand::new,
|
||||
CreateCommand::new
|
||||
CreateCommand::new,
|
||||
LoadCommand::new,
|
||||
SaveCommand::new,
|
||||
ConfigCommand::new
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requires(CommandSourceStack source) {
|
||||
return LeavesConfig.modify.fakeplayer.enable && source.getSender().hasPermission(PERM_BASE);
|
||||
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
|
||||
List<String> permissions = new ArrayList<>();
|
||||
permissions.add(PERM_BASE);
|
||||
permissions.addAll(this.children.stream().map(CommandNode::getName).toList());
|
||||
CommandUtils.registerPermissions(permissions);
|
||||
return super.compile();
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSourceStack source, String subcommand) {
|
||||
CommandSender sender = source.getSender();
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return children.stream().anyMatch(child -> child.requires(source));
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSender sender) {
|
||||
return sender.hasPermission(PERM_BASE);
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSender sender, String subcommand) {
|
||||
return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.leavesmc.leaves.neo_command.bot;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.neo_command.LiteralNode;
|
||||
|
||||
public abstract class BotSubcommand extends LiteralNode {
|
||||
|
||||
protected BotSubcommand(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return BotCommand.hasPermission(source.getSender(), this.name);
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,16 @@ package org.leavesmc.leaves.neo_command.bot.subcommands;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.LeavesConfig;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.neo_command.CommandContext;
|
||||
import org.leavesmc.leaves.neo_command.CustomArgumentNode;
|
||||
import org.leavesmc.leaves.neo_command.LiteralNode;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotSubcommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.action.ListCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.action.StartCommand;
|
||||
import org.leavesmc.leaves.neo_command.bot.subcommands.action.StopCommand;
|
||||
|
||||
public class ActionCommand extends LiteralNode {
|
||||
public class ActionCommand extends BotSubcommand {
|
||||
|
||||
public ActionCommand() {
|
||||
super("action");
|
||||
@@ -20,8 +20,8 @@ public class ActionCommand extends LiteralNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requires(CommandSourceStack source) {
|
||||
return BotCommand.hasPermission(source, "action");
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return LeavesConfig.modify.fakeplayer.canUseAction && super.requires(source);
|
||||
}
|
||||
|
||||
public static class BotArgument extends CustomArgumentNode<ServerBot, String> {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.leavesmc.leaves.neo_command.bot.subcommands;
|
||||
|
||||
import org.leavesmc.leaves.neo_command.bot.BotSubcommand;
|
||||
|
||||
public class ConfigCommand extends BotSubcommand {
|
||||
|
||||
public ConfigCommand() {
|
||||
super("config");
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,12 @@ import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.event.bot.BotCreateEvent;
|
||||
import org.leavesmc.leaves.neo_command.ArgumentNode;
|
||||
import org.leavesmc.leaves.neo_command.CommandContext;
|
||||
import org.leavesmc.leaves.neo_command.LiteralNode;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotSubcommand;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.minecraft.commands.arguments.DimensionArgument.getDimension;
|
||||
|
||||
public class CreateCommand extends LiteralNode {
|
||||
public class CreateCommand extends BotSubcommand {
|
||||
|
||||
public CreateCommand() {
|
||||
super("create");
|
||||
@@ -133,7 +133,7 @@ public class CreateCommand extends LiteralNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requires(@NotNull CommandSourceStack source) {
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return source.getSender() instanceof ConsoleCommandSender;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.neo_command.ArgumentNode;
|
||||
import org.leavesmc.leaves.neo_command.CommandContext;
|
||||
import org.leavesmc.leaves.neo_command.LiteralNode;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotSubcommand;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -31,7 +31,7 @@ import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||
import static net.minecraft.commands.arguments.DimensionArgument.getDimension;
|
||||
|
||||
|
||||
public class ListCommand extends LiteralNode {
|
||||
public class ListCommand extends BotSubcommand {
|
||||
|
||||
public ListCommand() {
|
||||
super("list");
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.leavesmc.leaves.neo_command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.LeavesConfig;
|
||||
import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.neo_command.ArgumentNode;
|
||||
import org.leavesmc.leaves.neo_command.CommandContext;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotSubcommand;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static io.papermc.paper.adventure.PaperAdventure.asAdventure;
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
|
||||
public class LoadCommand extends BotSubcommand {
|
||||
|
||||
public LoadCommand() {
|
||||
super("load");
|
||||
children(BotNameArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad && super.requires(source);
|
||||
}
|
||||
|
||||
private static class BotNameArgument extends ArgumentNode<String> {
|
||||
|
||||
public BotNameArgument() {
|
||||
super("bot_name", StringArgumentType.word());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
String botName = context.getArgument(BotNameArgument.class);
|
||||
BotList botList = BotList.INSTANCE;
|
||||
CommandSender sender = context.getSender();
|
||||
if (!botList.getSavedBotList().contains(botName)) {
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
|
||||
}
|
||||
|
||||
ServerBot bot = botList.loadNewBot(botName);
|
||||
if (bot == null) {
|
||||
sender.sendMessage(text("Failed to load bot, please check log", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
sender.sendMessage(join(
|
||||
spaces(),
|
||||
text("Successfully loaded bot", NamedTextColor.GRAY),
|
||||
asAdventure(bot.getDisplayName())
|
||||
));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<Suggestions> getSuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) {
|
||||
BotList botList = BotList.INSTANCE;
|
||||
Set<String> bots = botList.getSavedBotList().keySet();
|
||||
if (bots.isEmpty()) {
|
||||
return builder
|
||||
.suggest("<NO SAVED BOT EXISTS>", net.minecraft.network.chat.Component.literal("There are no bots saved before, save one first."))
|
||||
.buildFuture();
|
||||
}
|
||||
bots.forEach(builder::suggest);
|
||||
return builder.buildFuture();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.leavesmc.leaves.neo_command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.LeavesConfig;
|
||||
import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.event.bot.BotRemoveEvent;
|
||||
import org.leavesmc.leaves.neo_command.CommandContext;
|
||||
import org.leavesmc.leaves.neo_command.CustomArgumentNode;
|
||||
import org.leavesmc.leaves.neo_command.bot.BotSubcommand;
|
||||
|
||||
import static io.papermc.paper.adventure.PaperAdventure.asAdventure;
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
|
||||
public class SaveCommand extends BotSubcommand {
|
||||
|
||||
public SaveCommand() {
|
||||
super("save");
|
||||
children(BotArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad && super.requires(source);
|
||||
}
|
||||
|
||||
private static class BotArgument extends CustomArgumentNode<ServerBot, String> {
|
||||
|
||||
public BotArgument() {
|
||||
super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = context.getCustomArgument(BotArgument.class);
|
||||
CommandSender sender = context.getSender();
|
||||
BotList botList = BotList.INSTANCE;
|
||||
|
||||
if (!botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true)) {
|
||||
sender.sendMessage(text("Failed to save bot, please check log", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
sender.sendMessage(join(spaces(),
|
||||
text("Successfully saved bot", NamedTextColor.GRAY),
|
||||
asAdventure(bot.getDisplayName()),
|
||||
text("as " + bot.createState.realName(), NamedTextColor.GRAY)
|
||||
));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.leavesmc.leaves.neo_command.leaves;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.neo_command.WrappedArgument;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ArgumentSuggestions {
|
||||
@Contract(pure = true)
|
||||
public static WrappedArgument.@NotNull SuggestionApplier strings(String... values) {
|
||||
return (context, builder) -> {
|
||||
for (String s : values) {
|
||||
builder.suggest(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static WrappedArgument.@NotNull SuggestionApplier strings(List<String> values) {
|
||||
return (context, builder) -> {
|
||||
for (String s : values) {
|
||||
builder.suggest(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,41 @@
|
||||
package org.leavesmc.leaves.neo_command.leaves;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.neo_command.CommandNode;
|
||||
import org.leavesmc.leaves.neo_command.CommandUtils;
|
||||
import org.leavesmc.leaves.neo_command.LiteralNode;
|
||||
import org.leavesmc.leaves.neo_command.leaves.subcommands.ConfigCommand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LeavesCommand extends LiteralNode {
|
||||
public static final LeavesCommand INSTANCE = new LeavesCommand();
|
||||
private static final String PERM_BASE = "bukkit.command.leaves";
|
||||
|
||||
public LeavesCommand() {
|
||||
private LeavesCommand() {
|
||||
super("leaves_new");
|
||||
children(ConfigCommand::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requires(@NotNull CommandSourceStack source) {
|
||||
return source.getSender().hasPermission(PERM_BASE);
|
||||
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
|
||||
List<String> permissions = new ArrayList<>();
|
||||
permissions.add(PERM_BASE);
|
||||
permissions.addAll(this.children.stream().map(CommandNode::getName).toList());
|
||||
CommandUtils.registerPermissions(permissions);
|
||||
return super.compile();
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSourceStack source, String subcommand) {
|
||||
CommandSender sender = source.getSender();
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return children.stream().anyMatch(child -> child.requires(source));
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSender sender, String subcommand) {
|
||||
return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||
import static org.leavesmc.leaves.neo_command.CommandUtils.getListClosestMatchingLast;
|
||||
|
||||
public class ConfigCommand extends LiteralNode {
|
||||
|
||||
@@ -30,8 +31,8 @@ public class ConfigCommand extends LiteralNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requires(@NotNull CommandSourceStack source) {
|
||||
return LeavesCommand.hasPermission(source, "config");
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return LeavesCommand.hasPermission(source.getSender(), "config");
|
||||
}
|
||||
|
||||
private static class PathArgument extends ArgumentNode<String> {
|
||||
@@ -46,13 +47,10 @@ public class ConfigCommand extends LiteralNode {
|
||||
String path = context.getArgumentOrDefault(PathArgument.class, "");
|
||||
int dotIndex = path.lastIndexOf(".");
|
||||
builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2);
|
||||
LeavesCommandUtil.getListClosestMatchingLast(
|
||||
context.getSender(),
|
||||
getListClosestMatchingLast(
|
||||
path.substring(dotIndex + 1),
|
||||
GlobalConfigManager.getVerifiedConfigSubPaths(path),
|
||||
"bukkit.command.leaves"
|
||||
)
|
||||
.forEach(builder::suggest);
|
||||
GlobalConfigManager.getVerifiedConfigSubPaths(path)
|
||||
).forEach(builder::suggest);
|
||||
return builder.buildFuture();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user