From 463e408b0d0ed76832c02711d5468a7254bd8003 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Fri, 22 Aug 2025 09:54:53 +0800 Subject: [PATCH 01/29] feat: neo command --- .../features/0142-Leaves-Server-Command.patch | 18 +++ .../leaves/neo_command/ArgumentNode.java | 37 +++++ .../leaves/neo_command/CommandContext.java | 105 +++++++++++++ .../leaves/neo_command/CommandNode.java | 74 +++++++++ .../leaves/neo_command/LeavesCommand.java | 10 ++ .../leaves/neo_command/LeavesCommands.java | 11 ++ .../leaves/neo_command/LiteralNode.java | 25 +++ .../subcommands/ConfigCommand.java | 147 ++++++++++++++++++ 8 files changed, 427 insertions(+) create mode 100644 leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java diff --git a/leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch b/leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch new file mode 100644 index 00000000..17b8ad71 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MC_XiaoHei +Date: Fri, 22 Aug 2025 09:42:16 +0800 +Subject: [PATCH] Leaves Server Command + + +diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java +index ec1cced129ef42be65d7b2b622638bfae8bd895e..b54b1b56c8df6c6e03c2f53423b273a7c975a498 100644 +--- a/net/minecraft/commands/Commands.java ++++ b/net/minecraft/commands/Commands.java +@@ -182,6 +182,7 @@ public class Commands { + } + public Commands(Commands.CommandSelection selection, CommandBuildContext context, final boolean modern) { + // Paper end - Brigadier API - modern minecraft overloads that do not use redirects but are copies instead ++ org.leavesmc.leaves.neo_command.LeavesCommands.registerLeavesCommands(dispatcher); // Leaves Commands + AdvancementCommands.register(this.dispatcher); + AttributeCommand.register(this.dispatcher, context); + ExecuteCommand.register(this.dispatcher, context); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java new file mode 100644 index 00000000..518ebc13 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java @@ -0,0 +1,37 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; + +import java.util.concurrent.CompletableFuture; + +public abstract class ArgumentNode extends CommandNode { + private final ArgumentType argumentType; + + protected ArgumentNode(String name, ArgumentType argumentType) { + super(name); + this.argumentType = argumentType; + } + + @SuppressWarnings({"unused", "RedundantThrows"}) + protected CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { + return Suggestions.empty(); + } + + @Override + protected ArgumentBuilder compileBase() { + RequiredArgumentBuilder argumentBuilder = Commands.argument(name, argumentType); + if (isMethodOverridden("getSuggestions", ArgumentNode.class)) { + argumentBuilder.suggests( + (context, builder) -> getSuggestions(new CommandContext(context), builder) + ); + } + return argumentBuilder; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java new file mode 100644 index 00000000..5ecf61fa --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java @@ -0,0 +1,105 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.RedirectModifier; +import com.mojang.brigadier.context.ParsedCommandNode; +import com.mojang.brigadier.context.StringRange; +import com.mojang.brigadier.tree.CommandNode; +import net.minecraft.commands.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +import static org.leavesmc.leaves.neo_command.CommandNode.*; + +@SuppressWarnings({"ClassCanBeRecord", "unused"}) +public class CommandContext { + private final com.mojang.brigadier.context.CommandContext source; + + public CommandContext(com.mojang.brigadier.context.CommandContext source) { + this.source = source; + } + + public com.mojang.brigadier.context.CommandContext getChild() { + return source.getChild(); + } + + public com.mojang.brigadier.context.CommandContext getLastChild() { + return source.getLastChild(); + } + + public Command getCommand() { + return source.getCommand(); + } + + public CommandSourceStack getSource() { + return source.getSource(); + } + + public CommandSender getSender() { + return source.getSource().getSender(); + } + + public @NotNull V getArgument(final String name, final Class clazz) { + return source.getArgument(name, clazz); + } + + @SuppressWarnings("unchecked") + public @NotNull V getArgument(final Class> nodeClass) { + String name = getNameForNode(nodeClass); + return (V) source.getArgument(name, Object.class); + } + + public @NotNull V getArgumentOrDefault(final Class> nodeClass, final V defaultValue) { + try { + return getArgument(nodeClass); + } catch (IllegalArgumentException e) { + return defaultValue; + } + } + + public V getArgumentOrDefault(final String name, final Class clazz, final V defaultValue) { + try { + return source.getArgument(name, clazz); + } catch (IllegalArgumentException e) { + return defaultValue; + } + } + + public String getStringOrDefault(final String name, final String defaultValue) { + return getArgumentOrDefault(name, String.class, defaultValue); + } + + public int getIntegerOrDefault(final String name, final int defaultValue) { + return getArgumentOrDefault(name, Integer.class, defaultValue); + } + + public RedirectModifier getRedirectModifier() { + return source.getRedirectModifier(); + } + + public StringRange getRange() { + return source.getRange(); + } + + public String getInput() { + return source.getInput(); + } + + public CommandNode getRootNode() { + return source.getRootNode(); + } + + public List> getNodes() { + return source.getNodes(); + } + + public boolean hasNodes() { + return source.hasNodes(); + } + + public boolean isForked() { + return source.isForked(); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java new file mode 100644 index 00000000..a4971c32 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java @@ -0,0 +1,74 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import net.minecraft.commands.CommandSourceStack; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public abstract class CommandNode { + private static final Map, String> class2NameMap = new HashMap<>(); + + protected final String name; + protected final List children = new ArrayList<>(); + + protected CommandNode(String name) { + this.name = name; + class2NameMap.put(getClass(), name); + } + + @SafeVarargs + protected final void children(Supplier... childrenClasses) { + this.children.addAll(Stream.of(childrenClasses).map(Supplier::get).toList()); + } + + protected abstract ArgumentBuilder compileBase(); + + protected boolean execute(CommandContext context) { + return true; + } + + protected boolean requires(CommandSourceStack source) { + return true; + } + + protected ArgumentBuilder compile() { + ArgumentBuilder builder = compileBase(); + + if (isMethodOverridden("requires", CommandNode.class)) { + builder = builder.requires(this::requires); + } + + for (CommandNode child : children) { + builder = builder.then(child.compile()); + } + + if (isMethodOverridden("execute", CommandNode.class)) { + builder = builder.executes(mojangCtx -> { + CommandContext ctx = new CommandContext(mojangCtx); + return execute(ctx) ? 1 : 0; + }); + } + + return builder; + } + + protected boolean isMethodOverridden(String methodName, @NotNull Class baseClass) { + for (Method method : getClass().getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return method.getDeclaringClass() != baseClass; + } + } + return false; + } + + public static String getNameForNode(Class nodeClass) { + return class2NameMap.get(nodeClass); + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java new file mode 100644 index 00000000..8abe1f59 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java @@ -0,0 +1,10 @@ +package org.leavesmc.leaves.neo_command; + +import org.leavesmc.leaves.neo_command.subcommands.ConfigCommand; + +public class LeavesCommand extends LiteralNode { + public LeavesCommand() { + super("leaves_new"); + children(ConfigCommand::new); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java new file mode 100644 index 00000000..93e04589 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java @@ -0,0 +1,11 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandSourceStack; +import org.jetbrains.annotations.NotNull; + +public class LeavesCommands { + public static void registerLeavesCommands(@NotNull CommandDispatcher dispatcher) { + new LeavesCommand().register(dispatcher); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java new file mode 100644 index 00000000..0fa870ef --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java @@ -0,0 +1,25 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.CommandDispatcher; +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; + +public class LiteralNode extends CommandNode { + + protected LiteralNode(String name) { + super(name); + } + + @Override + protected ArgumentBuilder compileBase() { + return Commands.literal(name); + } + + @SuppressWarnings("unchecked") + public void register(@NotNull CommandDispatcher dispatcher) { + dispatcher.register((LiteralArgumentBuilder) compile()); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java new file mode 100644 index 00000000..4d39b887 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java @@ -0,0 +1,147 @@ +package org.leavesmc.leaves.neo_command.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.command.LeavesCommandUtil; +import org.leavesmc.leaves.config.GlobalConfigManager; +import org.leavesmc.leaves.config.VerifiedConfig; +import org.leavesmc.leaves.neo_command.ArgumentNode; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.LiteralNode; + +import java.util.concurrent.CompletableFuture; + +import static net.kyori.adventure.text.Component.text; + +public class ConfigCommand extends LiteralNode { + + public ConfigCommand() { + super("config"); + children(PathArgument::new); + } + + private static class PathArgument extends ArgumentNode { + + public PathArgument() { + super("path", StringArgumentType.string()); + children(ValueArgument::new); + } + + @Override + protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + String path = context.getArgumentOrDefault(PathArgument.class, ""); + int dotIndex = path.lastIndexOf("."); + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2); + LeavesCommandUtil.getListClosestMatchingLast( + context.getSender(), + path.substring(dotIndex + 1), + GlobalConfigManager.getVerifiedConfigSubPaths(path), + "bukkit.command.leaves.config" + ) + .forEach(builder::suggest); + return builder.buildFuture(); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + String path = context.getArgument(PathArgument.class); + VerifiedConfig verifiedConfig = getVerifiedConfig(context); + if (verifiedConfig == null) { + return false; + } + context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), + text("Config", NamedTextColor.GRAY), + text(path, NamedTextColor.AQUA), + text("value is", NamedTextColor.GRAY), + text(verifiedConfig.getString(), NamedTextColor.AQUA) + )); + return true; + } + + private static @Nullable VerifiedConfig getVerifiedConfig(@NotNull CommandContext context) { + String path = context.getArgument(PathArgument.class); + VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); + if (verifiedConfig == null) { + context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), + text("Config", NamedTextColor.GRAY), + text(path, NamedTextColor.RED), + text("is Not Found.", NamedTextColor.GRAY) + )); + return null; + } + return verifiedConfig; + } + + private static class ValueArgument extends ArgumentNode { + + public ValueArgument() { + super("value", StringArgumentType.greedyString()); + } + + @Override + protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + String path = context.getArgument(PathArgument.class); + String value = context.getArgumentOrDefault(ValueArgument.class, ""); + VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); + if (verifiedConfig == null) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("This config path does not exist.")) + .buildFuture(); + } + LeavesCommandUtil.getListMatchingLast( + context.getSender(), + new String[]{value}, + verifiedConfig.validator().valueSuggest() + ).forEach(builder::suggest); + return builder.buildFuture(); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + VerifiedConfig verifiedConfig = getVerifiedConfig(context); + String path = context.getArgument(PathArgument.class); + String value = context.getArgument(ValueArgument.class); + if (verifiedConfig == null) { + return false; + } + try { + verifiedConfig.set(value); + context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), + text("Config", NamedTextColor.GRAY), + text(path, NamedTextColor.AQUA), + text("changed to", NamedTextColor.GRAY), + text(verifiedConfig.getString(), NamedTextColor.AQUA) + )); + Bukkit.getOnlinePlayers() + .stream() + .filter(player -> player.hasPermission("leaves.command.config.notify") && player != context.getSender()) + .forEach( + player -> player.sendMessage(Component.join(JoinConfiguration.spaces(), + text(context.getSender().getName() + ":", NamedTextColor.GRAY), + text("Config", NamedTextColor.GRAY), + text(path, NamedTextColor.AQUA), + text("changed to", NamedTextColor.GRAY), + text(verifiedConfig.getString(), NamedTextColor.AQUA) + )) + ); + return true; + } catch (IllegalArgumentException exception) { + context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), + text("Config", NamedTextColor.GRAY), + text(path, NamedTextColor.RED), + text("modify error by", NamedTextColor.GRAY), + text(exception.getMessage(), NamedTextColor.RED) + )); + return false; + } + } + } + } +} \ No newline at end of file From 55061cfc5e42479a2c864c89c41b15dc4c617086 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Fri, 22 Aug 2025 22:49:26 +0800 Subject: [PATCH 02/29] feat: add action part --- .../features/0142-Leaves-Server-Command.patch | 18 - .../org/leavesmc/leaves/LeavesConfig.java | 2 + .../org/leavesmc/leaves/bot/BotCommand.java | 3 +- .../bot/agent/actions/ServerBotAction.java | 65 ++-- .../bot/agent/actions/ServerLookAction.java | 75 ++-- .../bot/agent/actions/ServerMountAction.java | 3 +- .../bot/agent/actions/ServerMoveAction.java | 29 +- .../agent/actions/ServerRotationAction.java | 38 +- .../bot/agent/actions/ServerSneakAction.java | 3 +- .../agent/actions/ServerStateBotAction.java | 6 +- .../bot/agent/actions/ServerSwapAction.java | 3 +- .../bot/agent/actions/ServerSwimAction.java | 3 +- .../agent/actions/ServerTimerBotAction.java | 42 +- .../bot/agent/actions/ServerUseBotAction.java | 26 +- .../bot/subcommands/BotActionCommand.java | 362 +++++++++--------- .../leaves/neo_command/ArgumentNode.java | 4 +- .../leaves/neo_command/CommandContext.java | 21 +- .../neo_command/CustomArgumentNode.java | 43 +++ .../neo_command/CustomArgumentType.java | 17 + .../leaves/neo_command/LeavesCommand.java | 10 - .../leaves/neo_command/LeavesCommands.java | 8 +- .../leaves/neo_command/WrappedArgument.java | 71 ++++ .../leaves/neo_command/bot/BotArgument.java | 44 +++ .../leaves/neo_command/bot/BotCommand.java | 29 ++ .../bot/subcommands/ActionCommand.java | 47 +++ .../bot/subcommands/action/ListCommand.java | 49 +++ .../bot/subcommands/action/StartCommand.java | 101 +++++ .../bot/subcommands/action/StopCommand.java | 131 +++++++ .../leaves/ArgumentSuggestions.java | 27 ++ .../neo_command/leaves/LeavesCommand.java | 26 ++ .../subcommands/ConfigCommand.java | 67 ++-- 31 files changed, 997 insertions(+), 376 deletions(-) delete mode 100644 leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java rename leaves-server/src/main/java/org/leavesmc/leaves/neo_command/{ => leaves}/subcommands/ConfigCommand.java (71%) diff --git a/leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch b/leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch deleted file mode 100644 index 17b8ad71..00000000 --- a/leaves-server/minecraft-patches/features/0142-Leaves-Server-Command.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MC_XiaoHei -Date: Fri, 22 Aug 2025 09:42:16 +0800 -Subject: [PATCH] Leaves Server Command - - -diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java -index ec1cced129ef42be65d7b2b622638bfae8bd895e..b54b1b56c8df6c6e03c2f53423b273a7c975a498 100644 ---- a/net/minecraft/commands/Commands.java -+++ b/net/minecraft/commands/Commands.java -@@ -182,6 +182,7 @@ public class Commands { - } - public Commands(Commands.CommandSelection selection, CommandBuildContext context, final boolean modern) { - // Paper end - Brigadier API - modern minecraft overloads that do not use redirects but are copies instead -+ org.leavesmc.leaves.neo_command.LeavesCommands.registerLeavesCommands(dispatcher); // Leaves Commands - AdvancementCommands.register(this.dispatcher); - AttributeCommand.register(this.dispatcher, context); - ExecuteCommand.register(this.dispatcher, context); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index c6844c73..f2e7325a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -30,6 +30,7 @@ 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; @@ -94,6 +95,7 @@ public static void init(final @NotNull File file) { GlobalConfigManager.init(); registerCommand("leaves", new LeavesCommand()); + LeavesCommands.registerLeavesCommands(); } public static void reload() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java index bf58ff5d..1a40ec37 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java @@ -2,7 +2,6 @@ import net.minecraft.Util; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.subcommands.BotActionCommand; import org.leavesmc.leaves.bot.subcommands.BotConfigCommand; import org.leavesmc.leaves.bot.subcommands.BotCreateCommand; import org.leavesmc.leaves.bot.subcommands.BotListCommand; @@ -24,7 +23,7 @@ public class BotCommand extends LeavesRootCommand { final Map, LeavesSubcommand> commands = new HashMap<>(); commands.put(Set.of("create"), new BotCreateCommand()); commands.put(Set.of("remove"), new BotRemoveCommand()); - commands.put(Set.of("action"), new BotActionCommand()); +// commands.put(Set.of("action"), new BotActionCommand()); commands.put(Set.of("config"), new BotConfigCommand()); commands.put(Set.of("save"), new BotSaveCommand()); commands.put(Set.of("load"), new BotLoadCommand()); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java index f92f25d7..c8e45d1e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java @@ -1,22 +1,24 @@ package org.leavesmc.leaves.bot.agent.actions; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; import org.leavesmc.leaves.event.bot.BotActionStopEvent; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.WrappedArgument; import org.leavesmc.leaves.util.UpdateSuppressionException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; -import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; @@ -24,9 +26,10 @@ public abstract class ServerBotAction> { private final String name; - private final CommandArgument argument; + private final Map>>> arguments; private final Supplier creator; private UUID uuid; + private int currentFork = 0; private int initialTickDelay; private int initialTickInterval; @@ -40,11 +43,11 @@ public abstract class ServerBotAction> { private Consumer onSuccess; private Consumer onStop; - public ServerBotAction(String name, CommandArgument argument, Supplier creator) { + public ServerBotAction(String name, Supplier creator) { this.name = name; - this.argument = argument; this.uuid = UUID.randomUUID(); this.creator = creator; + this.arguments = new HashMap<>(); this.cancel = false; this.setStartDelayTick(0); @@ -56,12 +59,39 @@ public ServerBotAction(String name, CommandArgument argument, Supplier creato public abstract Object asCraft(); + public List> provideReadableActionData() { + return new ArrayList<>(); + } + + public String getReadableActionDataString() { + return provideReadableActionData().stream() + .map(pair -> pair.getLeft() + "=" + pair.getRight()) + .reduce((a, b) -> a + ", " + b) + .orElse("No arguments"); + } + public void init() { this.tickToNext = initialTickDelay; this.numberRemaining = this.getDoNumber(); this.setCancelled(false); } + public void fork(int fork) { + currentFork = fork; + } + + public WrappedArgument addArgument(String name, ArgumentType type) { + WrappedArgument argument = new WrappedArgument<>(name, type); + this.arguments + .computeIfAbsent(currentFork, k -> new ArrayList<>()) + .add(Pair.of(name, argument)); + return argument; + } + + public Map>>> getArguments() { + return this.arguments; + } + public void tryTick(ServerBot bot) { if (this.numberRemaining == 0) { this.stop(bot, BotActionStopEvent.Reason.DONE); @@ -149,19 +179,8 @@ public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) { } } - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - } - - public void setSuggestion(int n, BiFunction, String>> suggestion) { - this.argument.setSuggestion(n, suggestion); - } - - public void setSuggestion(int n, Pair, String> suggestion) { - this.setSuggestion(n, (sender, arg) -> suggestion); - } - - public void setSuggestion(int n, List tabComplete) { - this.setSuggestion(n, Pair.of(tabComplete, null)); + @SuppressWarnings("RedundantThrows") + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { } @NotNull @@ -169,10 +188,6 @@ public E create() { return this.creator.get(); } - public CommandArgument getArgument() { - return this.argument; - } - public String getName() { return this.name; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index abc10852..3b1eddea 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -1,39 +1,60 @@ package org.leavesmc.leaves.bot.agent.actions; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.commands.arguments.coordinates.Coordinates; +import net.minecraft.commands.arguments.coordinates.Vec3Argument; +import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.entity.Player; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; - -import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Stream; +import org.leavesmc.leaves.neo_command.CommandContext; public class ServerLookAction extends ServerBotAction { private static final Vector ZERO_VECTOR = new Vector(0, 0, 0); - private static final DecimalFormat DF = new DecimalFormat("0.0"); private Vector pos = ZERO_VECTOR; private ServerPlayer target = null; public ServerLookAction() { - super("look", CommandArgument.of(CommandArgumentType.STRING, CommandArgumentType.DOUBLE, CommandArgumentType.DOUBLE), ServerLookAction::new); - this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ? - Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of(DF.format(player.getX()))).toList(), "|") : - Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of("0")).toList(), "|") - ); - this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getY())), "") : Pair.of(List.of("0"), "")); - this.setSuggestion(2, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getZ())), "") : Pair.of(List.of("0"), "")); + super("look", ServerLookAction::new); + declarePlayerBranch(); + declareLocationBranch(); + } + + private void declarePlayerBranch() { + this.fork(0); + this.addArgument("player", EntityArgument.player()) + .setOptional(true); + } + + private void declareLocationBranch() { + this.fork(1); + this.addArgument("location", Vec3Argument.vec3(false)); + } + + @Override + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { + EntitySelector selector = context.getArgumentOrDefault("player", EntitySelector.class, null); + Coordinates location = context.getArgumentOrDefault("location", Coordinates.class, null); + CommandSourceStack source = context.getSource(); + if (selector == null && location == null) { + Entity sender = source.getEntityOrException(); + this.setPos(new Vector(sender.getX(), sender.getY(), sender.getZ())); + } else if (selector != null) { + ServerPlayer player = selector.findSinglePlayer(source); + this.setTarget(player); + } else { + Vec3 vector = location.getPosition(source); + this.setPos(new Vector(vector.x, vector.y, vector.z)); + } } @Override @@ -87,22 +108,6 @@ public boolean doTick(@NotNull ServerBot bot) { return true; } - @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - String nameOrX = result.readString(player.getScoreboardName()); - ServerPlayer player1 = player.getServer().getPlayerList().getPlayerByName(nameOrX); - if (player1 != null) { - this.setTarget(player1); - return; - } - try { - Vector vector = result.readVectorYZ(Double.parseDouble(nameOrX)); - this.setPos(vector); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid vector"); - } - } - @Override public Object asCraft() { return new CraftLookAction(this); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java index c4a4a440..3719200b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java @@ -6,7 +6,6 @@ import org.bukkit.entity.Vehicle; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftMountAction; import java.util.Comparator; @@ -15,7 +14,7 @@ public class ServerMountAction extends ServerBotAction { public ServerMountAction() { - super("mount", CommandArgument.EMPTY, ServerMountAction::new); + super("mount", ServerMountAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 6f3e8b80..bd3c2f62 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -1,37 +1,34 @@ package org.leavesmc.leaves.bot.agent.actions; -import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; +import com.mojang.brigadier.arguments.StringArgumentType; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; +import org.leavesmc.leaves.neo_command.CommandContext; import java.util.Arrays; -import java.util.List; + +import static org.leavesmc.leaves.neo_command.leaves.ArgumentSuggestions.strings; public class ServerMoveAction extends ServerStateBotAction { - private static final Pair, String> suggestions = Pair.of( - Arrays.stream(MoveDirection.values()).map((it) -> it.name).toList(), - "" - ); private MoveDirection direction = MoveDirection.FORWARD; public ServerMoveAction() { - super("move", CommandArgument.of(CommandArgumentType.ofEnum(MoveDirection.class)), ServerMoveAction::new); - this.setSuggestion(0, suggestions); + super("move", ServerMoveAction::new); + this.addArgument("direction", StringArgumentType.word()) + .suggests(strings(Arrays.stream(MoveDirection.values()).map(MoveDirection::name).toList())); } @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - this.direction = result.read(MoveDirection.class); - if (direction == null) { - throw new IllegalArgumentException("Invalid direction"); + public void loadCommand(@NotNull CommandContext context) { + String raw = context.getArgument("direction", String.class); + try { + this.direction = MoveDirection.valueOf(raw); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Invalid move direction: " + raw); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 0c278ea4..5cbc26aa 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -1,41 +1,43 @@ package org.leavesmc.leaves.bot.agent.actions; +import com.mojang.brigadier.arguments.FloatArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.entity.Player; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; +import org.leavesmc.leaves.neo_command.CommandContext; import java.text.DecimalFormat; -import java.util.List; -import java.util.Objects; public class ServerRotationAction extends ServerBotAction { private static final DecimalFormat DF = new DecimalFormat("0.00"); public ServerRotationAction() { - super("rotation", CommandArgument.of(CommandArgumentType.FLOAT, CommandArgumentType.FLOAT), ServerRotationAction::new); - this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getYaw())), "[yaw]") : Pair.of(List.of("0"), "")); - this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getPitch())), "[pitch]") : Pair.of(List.of("0"), "")); + super("rotation", ServerRotationAction::new); + this.addArgument("yaw", FloatArgumentType.floatArg(-180, 180)) + .suggests((context, builder) -> builder.suggest( + DF.format(context.getSource().getEntityOrException().getYRot()), + Component.literal("current player yaw") + )) + .setOptional(true); + this.addArgument("pitch", FloatArgumentType.floatArg(-90, 90)) + .suggests((context, builder) -> builder.suggest( + DF.format(context.getSource().getEntityOrException().getXRot()), + Component.literal("current player pitch") + )) + .setOptional(true); } private float yaw = 0.0f; private float pitch = 0.0f; @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - try { - this.yaw = result.readFloat(Objects.requireNonNull(player).getYRot()); - this.pitch = result.readFloat(player.getXRot()); - } catch (Exception e) { - throw new IllegalArgumentException("No valid rotation specified", e); - } + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { + this.yaw = context.getFloatOrDefault("yaw", context.getSource().getEntityOrException().getYRot()); + this.pitch = context.getFloatOrDefault("pitch", context.getSource().getEntityOrException().getXRot()); } public void setYaw(float yaw) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java index 104cb194..8476669a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java @@ -2,14 +2,13 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; public class ServerSneakAction extends ServerStateBotAction { public ServerSneakAction() { - super("sneak", CommandArgument.EMPTY, ServerSneakAction::new); + super("sneak", ServerSneakAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java index c67b7acb..c87f1ffc 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java @@ -1,13 +1,11 @@ package org.leavesmc.leaves.bot.agent.actions; -import org.leavesmc.leaves.command.CommandArgument; - import java.util.function.Supplier; public abstract class ServerStateBotAction> extends ServerBotAction { - public ServerStateBotAction(String name, CommandArgument argument, Supplier creator) { - super(name, argument, creator); + public ServerStateBotAction(String name, Supplier creator) { + super(name, creator); this.setDoNumber(-1); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java index 8363b11d..9f6e7efc 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java @@ -4,13 +4,12 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction; public class ServerSwapAction extends ServerBotAction { public ServerSwapAction() { - super("swap", CommandArgument.EMPTY, ServerSwapAction::new); + super("swap", ServerSwapAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java index 50576fe6..fce55dc5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java @@ -3,13 +3,12 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction; public class ServerSwimAction extends ServerStateBotAction { public ServerSwimAction() { - super("swim", CommandArgument.EMPTY, ServerSwimAction::new); + super("swim", ServerSwimAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java index 40edda63..81edbeb0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java @@ -1,32 +1,46 @@ package org.leavesmc.leaves.bot.agent.actions; -import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.chat.Component; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.neo_command.CommandContext; +import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; +import static org.leavesmc.leaves.neo_command.leaves.ArgumentSuggestions.strings; + public abstract class ServerTimerBotAction> extends ServerBotAction { public ServerTimerBotAction(String name, Supplier creator) { - this(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), creator); + super(name, creator); + this.addArgument("delay", integer(0)) + .suggests(strings("0", "5", "10", "20")) + .setOptional(true); + this.addArgument("interval", integer(0)) + .suggests(strings("20", "0", "5", "10")) + .setOptional(true); + this.addArgument("do_number", integer(-1)) + .suggests(((context, builder) -> builder.suggest("-1", Component.literal("do infinite times")))) + .setOptional(true); } - public ServerTimerBotAction(String name, CommandArgument argument, Supplier creator) { - super(name, argument, creator); - this.setSuggestion(0, Pair.of(List.of("0"), "[TickDelay]")); - this.setSuggestion(1, Pair.of(List.of("20"), "[TickInterval]")); - this.setSuggestion(2, Pair.of(List.of("1", "-1"), "[DoNumber]")); + @Override + public void loadCommand(@NotNull CommandContext context) { + this.setStartDelayTick(context.getIntegerOrDefault("delay", 0)); + this.setDoIntervalTick(context.getIntegerOrDefault("interval", 20)); + this.setDoNumber(context.getIntegerOrDefault("do_number", 1)); } @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setStartDelayTick(result.readInt(0)); - this.setDoIntervalTick(result.readInt(20)); - this.setDoNumber(result.readInt(1)); + public List> provideReadableActionData() { + return new ArrayList<>(List.of( + Pair.of("delay", String.valueOf(this.getStartDelayTick())), + Pair.of("interval", String.valueOf(this.getDoIntervalTick())), + Pair.of("do_number", String.valueOf(this.getDoNumber())), + Pair.of("remaining_do_number", String.valueOf(this.getDoNumberRemaining())) + )); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java index 48c7a29d..a8292447 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java @@ -1,33 +1,37 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionResult; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; import org.leavesmc.leaves.event.bot.BotActionStopEvent; +import org.leavesmc.leaves.neo_command.CommandContext; -import java.util.List; import java.util.function.Supplier; +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; + public abstract class ServerUseBotAction> extends ServerTimerBotAction { private int useTickTimeout = -1; private int alreadyUsedTick = 0; private int useItemRemainingTicks = 0; public ServerUseBotAction(String name, Supplier supplier) { - super(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), supplier); - this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTickTimeout]")); + super(name, supplier); + this.addArgument("use_timeout", integer(-1)) + .suggests((context, builder) -> { + builder.suggest("-1", Component.literal("no use timeout")); + builder.suggest("3", Component.literal("minimum bow shoot time")); + builder.suggest("10", Component.literal("minimum trident shoot time")); + }) + .setOptional(true); } @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - super.loadCommand(player, result); - this.useTickTimeout = result.readInt(-1); + public void loadCommand(@NotNull CommandContext context) { + super.loadCommand(context); + this.useTickTimeout = context.getIntegerOrDefault("use_timeout", -1); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java index ce938659..c8c933ec 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java @@ -1,181 +1,181 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.network.chat.Component; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.bukkit.craftbukkit.entity.CraftPlayer; -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.bot.agent.Actions; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotActionStopEvent; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static net.kyori.adventure.text.Component.text; - -public class BotActionCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 2) { - sender.sendMessage(text("Use /bot action to make fakeplayer do action", NamedTextColor.RED)); - return; - } - - ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - switch (args[1].toLowerCase()) { - case "list" -> { - sender.sendMessage(bot.getScoreboardName() + "'s action list:"); - for (int i = 0; i < bot.getBotActions().size(); i++) { - sender.sendMessage(i + " " + bot.getBotActions().get(i).getName()); - } - } - case "start" -> executeStart(bot, sender, args); - case "stop" -> executeStop(bot, sender, args); - } - } - - private void executeStart(ServerBot bot, CommandSender sender, String[] args) { - if (args.length < 3) { - sender.sendMessage(text("Invalid action", NamedTextColor.RED)); - return; - } - ServerBotAction action = Actions.getForName(args[2]); - if (action == null) { - sender.sendMessage(text("Invalid action", NamedTextColor.RED)); - return; - } - - CraftPlayer player; - if (sender instanceof CraftPlayer) { - player = (CraftPlayer) sender; - } else { - player = bot.getBukkitEntity(); - } - - String[] realArgs = Arrays.copyOfRange(args, 3, args.length); - ServerBotAction newAction; - try { - newAction = action.create(); - newAction.loadCommand(player.getHandle(), action.getArgument().parse(0, realArgs)); - } catch (IllegalArgumentException e) { - sender.sendMessage(text("Action create error, please check your arguments, " + e.getMessage(), NamedTextColor.RED)); - return; - } - - if (bot.addBotAction(newAction, sender)) { - sender.sendMessage("Action " + action.getName() + " has been issued to " + bot.getName().getString()); - } - } - - private void executeStop(ServerBot bot, CommandSender sender, String[] args) { - if (args.length < 3) { - sender.sendMessage(text("Invalid index", NamedTextColor.RED)); - return; - } - - String index = args[2]; - if (index.equals("all")) { - Set> forRemoval = new HashSet<>(); - for (int i = 0; i < bot.getBotActions().size(); i++) { - ServerBotAction action = bot.getBotActions().get(i); - BotActionStopEvent event = new BotActionStopEvent( - bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender - ); - event.callEvent(); - if (!event.isCancelled()) { - forRemoval.add(action); - action.stop(bot, BotActionStopEvent.Reason.COMMAND); - } - } - bot.getBotActions().removeAll(forRemoval); - sender.sendMessage(bot.getScoreboardName() + "'s action list cleared."); - return; - } - try { - int i = Integer.parseInt(index); - if (i < 0 || i >= bot.getBotActions().size()) { - sender.sendMessage(text("Invalid index", NamedTextColor.RED)); - return; - } - - ServerBotAction action = bot.getBotActions().get(i); - BotActionStopEvent event = new BotActionStopEvent( - bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender - ); - event.callEvent(); - if (!event.isCancelled()) { - action.stop(bot, BotActionStopEvent.Reason.COMMAND); - bot.getBotActions().remove(i); - sender.sendMessage(bot.getScoreboardName() + "'s " + action.getName() + " stopped."); - - } - } catch (NumberFormatException e) { - sender.sendMessage(text("Invalid index", NamedTextColor.RED)); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String subCommand, String @NotNull [] args, Location location, @NotNull LeavesSuggestionBuilder builder) { - BotList botList = BotList.INSTANCE; - ServerBot serverBot = null; - - if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { - builder.suggest("<" + args[0] + " not found>"); - return; - } - - switch (args.length) { - case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - case 2 -> builder.suggest("start").suggest("stop").suggest("list"); - case 3 -> { - switch (args[1].toLowerCase()) { - case "start" -> Actions.getNames().forEach(builder::suggest); - case "stop" -> { - builder.suggest("all"); - int[] index = new int[]{0}; - serverBot.getBotActions().forEach(a -> builder.suggest(String.valueOf(index[0]++))); - } - } - } - case 4, 5, 6, 7 -> { - ServerBotAction action = Actions.getForName(args[2]); - if (action == null) { - return; - } - Pair, String> results = action.getArgument().suggestion(args.length - 4, sender, args[args.length - 2]); - if (results == null || results.getLeft() == null) { - return; - } - - for (String s : results.getLeft()) { - if (results.getRight() != null) { - builder.suggest(s, Component.literal(results.getRight())); - } else { - builder.suggest(s); - } - } - } - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canUseAction; - } -} +//package org.leavesmc.leaves.bot.subcommands; +// +//import net.kyori.adventure.text.format.NamedTextColor; +//import net.minecraft.network.chat.Component; +//import org.apache.commons.lang3.tuple.Pair; +//import org.bukkit.Location; +//import org.bukkit.command.CommandSender; +//import org.bukkit.craftbukkit.entity.CraftPlayer; +//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.bot.agent.Actions; +//import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +//import org.leavesmc.leaves.command.LeavesSubcommand; +//import org.leavesmc.leaves.command.LeavesSuggestionBuilder; +//import org.leavesmc.leaves.event.bot.BotActionStopEvent; +// +//import java.util.Arrays; +//import java.util.HashSet; +//import java.util.List; +//import java.util.Set; +// +//import static net.kyori.adventure.text.Component.text; +// +//public class BotActionCommand implements LeavesSubcommand { +// +// @Override +// public void execute(CommandSender sender, String subCommand, String[] args) { +// if (args.length < 2) { +// sender.sendMessage(text("Use /bot action to make fakeplayer do action", NamedTextColor.RED)); +// return; +// } +// +// ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); +// if (bot == null) { +// sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); +// return; +// } +// +// switch (args[1].toLowerCase()) { +// case "list" -> { +// sender.sendMessage(bot.getScoreboardName() + "'s action list:"); +// for (int i = 0; i < bot.getBotActions().size(); i++) { +// sender.sendMessage(i + " " + bot.getBotActions().get(i).getName()); +// } +// } +// case "start" -> executeStart(bot, sender, args); +// case "stop" -> executeStop(bot, sender, args); +// } +// } +// +// private void executeStart(ServerBot bot, CommandSender sender, String[] args) { +// if (args.length < 3) { +// sender.sendMessage(text("Invalid action", NamedTextColor.RED)); +// return; +// } +// ServerBotAction action = Actions.getForName(args[2]); +// if (action == null) { +// sender.sendMessage(text("Invalid action", NamedTextColor.RED)); +// return; +// } +// +// CraftPlayer player; +// if (sender instanceof CraftPlayer) { +// player = (CraftPlayer) sender; +// } else { +// player = bot.getBukkitEntity(); +// } +// +// String[] realArgs = Arrays.copyOfRange(args, 3, args.length); +// ServerBotAction newAction; +// try { +// newAction = action.create(); +// newAction.loadCommand(player.getHandle(), action.getArgument().parse(0, realArgs)); +// } catch (IllegalArgumentException e) { +// sender.sendMessage(text("Action create error, please check your arguments, " + e.getMessage(), NamedTextColor.RED)); +// return; +// } +// +// if (bot.addBotAction(newAction, sender)) { +// sender.sendMessage("Action " + action.getName() + " has been issued to " + bot.getName().getString()); +// } +// } +// +// private void executeStop(ServerBot bot, CommandSender sender, String[] args) { +// if (args.length < 3) { +// sender.sendMessage(text("Invalid index", NamedTextColor.RED)); +// return; +// } +// +// String index = args[2]; +// if (index.equals("all")) { +// Set> forRemoval = new HashSet<>(); +// for (int i = 0; i < bot.getBotActions().size(); i++) { +// ServerBotAction action = bot.getBotActions().get(i); +// BotActionStopEvent event = new BotActionStopEvent( +// bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender +// ); +// event.callEvent(); +// if (!event.isCancelled()) { +// forRemoval.add(action); +// action.stop(bot, BotActionStopEvent.Reason.COMMAND); +// } +// } +// bot.getBotActions().removeAll(forRemoval); +// sender.sendMessage(bot.getScoreboardName() + "'s action list cleared."); +// return; +// } +// try { +// int i = Integer.parseInt(index); +// if (i < 0 || i >= bot.getBotActions().size()) { +// sender.sendMessage(text("Invalid index", NamedTextColor.RED)); +// return; +// } +// +// ServerBotAction action = bot.getBotActions().get(i); +// BotActionStopEvent event = new BotActionStopEvent( +// bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender +// ); +// event.callEvent(); +// if (!event.isCancelled()) { +// action.stop(bot, BotActionStopEvent.Reason.COMMAND); +// bot.getBotActions().remove(i); +// sender.sendMessage(bot.getScoreboardName() + "'s " + action.getName() + " stopped."); +// +// } +// } catch (NumberFormatException e) { +// sender.sendMessage(text("Invalid index", NamedTextColor.RED)); +// } +// } +// +// @Override +// public void suggest(@NotNull CommandSender sender, @NotNull String subCommand, String @NotNull [] args, Location location, @NotNull LeavesSuggestionBuilder builder) { +// BotList botList = BotList.INSTANCE; +// ServerBot serverBot = null; +// +// if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { +// builder.suggest("<" + args[0] + " not found>"); +// return; +// } +// +// switch (args.length) { +// case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); +// case 2 -> builder.suggest("start").suggest("stop").suggest("list"); +// case 3 -> { +// switch (args[1].toLowerCase()) { +// case "start" -> Actions.getNames().forEach(builder::suggest); +// case "stop" -> { +// builder.suggest("all"); +// int[] index = new int[]{0}; +// serverBot.getBotActions().forEach(a -> builder.suggest(String.valueOf(index[0]++))); +// } +// } +// } +// case 4, 5, 6, 7 -> { +// ServerBotAction action = Actions.getForName(args[2]); +// if (action == null) { +// return; +// } +// Pair, String> results = action.getArgument().suggestion(args.length - 4, sender, args[args.length - 2]); +// if (results == null || results.getLeft() == null) { +// return; +// } +// +// for (String s : results.getLeft()) { +// if (results.getRight() != null) { +// builder.suggest(s, Component.literal(results.getRight())); +// } else { +// builder.suggest(s); +// } +// } +// } +// } +// } +// +// @Override +// public boolean isEnabled() { +// return LeavesConfig.modify.fakeplayer.canUseAction; +// } +//} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java index 518ebc13..8f9aea04 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java @@ -12,7 +12,7 @@ import java.util.concurrent.CompletableFuture; public abstract class ArgumentNode extends CommandNode { - private final ArgumentType argumentType; + protected final ArgumentType argumentType; protected ArgumentNode(String name, ArgumentType argumentType) { super(name); @@ -27,11 +27,13 @@ protected CompletableFuture getSuggestions(final CommandContext con @Override protected ArgumentBuilder compileBase() { RequiredArgumentBuilder argumentBuilder = Commands.argument(name, argumentType); + if (isMethodOverridden("getSuggestions", ArgumentNode.class)) { argumentBuilder.suggests( (context, builder) -> getSuggestions(new CommandContext(context), builder) ); } + return argumentBuilder; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java index 5ecf61fa..2796ee16 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java @@ -11,7 +11,7 @@ import java.util.List; -import static org.leavesmc.leaves.neo_command.CommandNode.*; +import static org.leavesmc.leaves.neo_command.CommandNode.getNameForNode; @SuppressWarnings({"ClassCanBeRecord", "unused"}) public class CommandContext { @@ -51,6 +51,13 @@ public CommandSender getSender() { return (V) source.getArgument(name, Object.class); } + @SuppressWarnings("unchecked") + public @NotNull V getCustomArgument(final Class> nodeClass) { + String name = getNameForNode(nodeClass); + T raw = (T) source.getArgument(name, Object.class); + return CustomArgumentNode.transform(nodeClass, raw); + } + public @NotNull V getArgumentOrDefault(final Class> nodeClass, final V defaultValue) { try { return getArgument(nodeClass); @@ -67,6 +74,14 @@ public V getArgumentOrDefault(final String name, final Class clazz, final } } + public V getCustomArgumentOrDefault(final Class> nodeClass, final V defaultValue) { + try { + return getCustomArgument(nodeClass); + } catch (IllegalArgumentException e) { + return defaultValue; + } + } + public String getStringOrDefault(final String name, final String defaultValue) { return getArgumentOrDefault(name, String.class, defaultValue); } @@ -75,6 +90,10 @@ public int getIntegerOrDefault(final String name, final int defaultValue) { return getArgumentOrDefault(name, Integer.class, defaultValue); } + public float getFloatOrDefault(final String name, final float defaultValue) { + return getArgumentOrDefault(name, Float.class, defaultValue); + } + public RedirectModifier getRedirectModifier() { return source.getRedirectModifier(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java new file mode 100644 index 00000000..9c7a5240 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java @@ -0,0 +1,43 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import net.minecraft.commands.CommandSourceStack; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +public class CustomArgumentNode extends ArgumentNode { + @SuppressWarnings("rawtypes") + private static final Map, CustomArgumentType> TYPES = new HashMap<>(); + + protected CustomArgumentNode(String name, @NotNull CustomArgumentType argumentType) { + super(name, argumentType.getBaseArgumentType()); + TYPES.put(getClass(), argumentType); + } + + public static T transform(Class> nodeClass, B base) { + @SuppressWarnings("unchecked") + CustomArgumentType type = (CustomArgumentType) TYPES.get(nodeClass); + if (type == null) { + throw new IllegalArgumentException("No custom argument type registered for " + nodeClass.getName()); + } + return type.transform(base); + } + + @Override + @SuppressWarnings("unchecked") + protected ArgumentBuilder compileBase() { + RequiredArgumentBuilder argumentBuilder = (RequiredArgumentBuilder) super.compileBase(); + + if (!isMethodOverridden("getSuggestions", ArgumentNode.class)) { + CustomArgumentType customArgumentType = (CustomArgumentType) TYPES.get(getClass()); + argumentBuilder.suggests( + (context, builder) -> customArgumentType.getSuggestions(new CommandContext(context), builder) + ); + } + + return argumentBuilder; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java new file mode 100644 index 00000000..f8c076b6 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java @@ -0,0 +1,17 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import java.util.concurrent.CompletableFuture; + +public interface CustomArgumentType { + + ArgumentType getBaseArgumentType(); + + T transform(B value); + + CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException; +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java deleted file mode 100644 index 8abe1f59..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommand.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.leavesmc.leaves.neo_command; - -import org.leavesmc.leaves.neo_command.subcommands.ConfigCommand; - -public class LeavesCommand extends LiteralNode { - public LeavesCommand() { - super("leaves_new"); - children(ConfigCommand::new); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java index 93e04589..b16cda68 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java @@ -2,10 +2,14 @@ import com.mojang.brigadier.CommandDispatcher; import net.minecraft.commands.CommandSourceStack; -import org.jetbrains.annotations.NotNull; +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(@NotNull CommandDispatcher dispatcher) { + public static void registerLeavesCommands() { + CommandDispatcher dispatcher = MinecraftServer.getServer().getCommands().getDispatcher(); new LeavesCommand().register(dispatcher); + new BotCommand().register(dispatcher); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java new file mode 100644 index 00000000..cda1a019 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java @@ -0,0 +1,71 @@ +package org.leavesmc.leaves.neo_command; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; + +import java.util.concurrent.CompletableFuture; + +public class WrappedArgument { + private final String name; + private final ArgumentType type; + private AsyncSuggestionProvider asyncSuggestionProvider = null; + private SuggestionApplier suggestionApplier = null; + private boolean optional = false; + + public WrappedArgument(String name, ArgumentType type) { + this.name = name; + this.type = type; + } + + public WrappedArgument suggestsAsync(AsyncSuggestionProvider provider) { + this.asyncSuggestionProvider = provider; + return this; + } + + public WrappedArgument suggests(SuggestionApplier provider) { + this.suggestionApplier = provider; + return this; + } + + public WrappedArgument setOptional(boolean optional) { + this.optional = optional; + return this; + } + + public boolean isOptional() { + return optional; + } + + public RequiredArgumentBuilder compile() { + RequiredArgumentBuilder builder = Commands.argument(name, type); + if (asyncSuggestionProvider != null) { + builder.suggests( + (context, b) -> + asyncSuggestionProvider.getSuggestions(new CommandContext(context), b) + ); + } else if (suggestionApplier != null) { + builder.suggests( + (context, b) -> { + suggestionApplier.applySuggestions(new CommandContext(context), b); + return CompletableFuture.completedFuture(b.build()); + } + ); + } + return builder; + } + + @FunctionalInterface + public interface SuggestionApplier { + void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } + + @FunctionalInterface + public interface AsyncSuggestionProvider { + CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java new file mode 100644 index 00000000..08b88409 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java @@ -0,0 +1,44 @@ +package org.leavesmc.leaves.neo_command.bot; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.entity.bot.Bot; +import org.leavesmc.leaves.entity.bot.CraftBot; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.CustomArgumentType; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public class BotArgument implements CustomArgumentType { + @Override + public ArgumentType getBaseArgumentType() { + return StringArgumentType.string(); + } + + @Override + public ServerBot transform(String value) { + CraftBot craftBot = (CraftBot) Bukkit.getBotManager().getBot(value); + if (craftBot == null) { + return null; + } + return craftBot.getHandle(); + } + + @Override + public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { + Collection bots = Bukkit.getBotManager().getBots(); + if (bots.isEmpty()) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("There are no bots in the server, create one first.")) + .buildFuture(); + } + bots.stream().map(Player::getName).forEach(builder::suggest); + return builder.buildFuture(); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java new file mode 100644 index 00000000..918ed621 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java @@ -0,0 +1,29 @@ +package org.leavesmc.leaves.neo_command.bot; + +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.LiteralNode; +import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand; + +public class BotCommand extends LiteralNode { + private static final String PERM_BASE = "bukkit.command.bot"; + + public BotCommand() { + super("bot_neo"); + this.children( + ActionCommand::new + ); + } + + @Override + protected boolean requires(CommandSourceStack source) { + return LeavesConfig.modify.fakeplayer.enable && source.getSender().hasPermission(PERM_BASE); + } + + public static boolean hasPermission(@NotNull CommandSourceStack source, String subcommand) { + CommandSender sender = source.getSender(); + return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java new file mode 100644 index 00000000..ad349d11 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java @@ -0,0 +1,47 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands; + +import net.minecraft.commands.CommandSourceStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +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.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 ActionCommand() { + super("action"); + children(ActionCommand.BotArgument::new); + } + + @Override + protected boolean requires(CommandSourceStack source) { + return BotCommand.hasPermission(source, "action"); + } + + public static class BotArgument extends CustomArgumentNode { + + protected BotArgument() { + super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + children( + StartCommand::new, + StopCommand::new, + ListCommand::new + ); + } + + public static @Nullable ServerBot getBot(@NotNull CommandContext context) { + try { + return context.getCustomArgument(BotArgument.class); + } catch (IllegalArgumentException e) { + context.getSender().sendMessage("This bot does not exist."); + return null; + } + } + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java new file mode 100644 index 00000000..3a32a4b7 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java @@ -0,0 +1,49 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands.action; + +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.LiteralNode; +import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand; + +import java.util.List; + +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.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class ListCommand extends LiteralNode { + + public ListCommand() { + super("list"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + if (bot == null) { + return false; + } + + List> actions = bot.getBotActions(); + if (actions.isEmpty()) { + context.getSender().sendMessage("This bot has no active actions"); + return true; + } + + context.getSender().sendMessage(bot.getScoreboardName() + "'s action list:"); + for (int i = 0; i < actions.size(); i++) { + ServerBotAction action = actions.get(i); + context.getSender().sendMessage(join(spaces(), + text(i, GRAY), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getReadableActionDataString()))) + )); + } + + return true; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java new file mode 100644 index 00000000..0ac8073d --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java @@ -0,0 +1,101 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands.action; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.commands.CommandSourceStack; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.Actions; +import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.LiteralNode; +import org.leavesmc.leaves.neo_command.WrappedArgument; + +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +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; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand.BotArgument.getBot; + +public class StartCommand extends LiteralNode { + + public StartCommand() { + super("start"); + Actions.getAll() + .stream() + .map(this::actionNodeCreator) + .forEach(this::children); + } + + private boolean executor(CommandContext context, @NotNull ServerBotAction action) throws CommandSyntaxException { + ServerBot bot = getBot(context); + CommandSender sender = context.getSender(); + if (bot == null) { + return false; + } + action.loadCommand(context); + if (bot.addBotAction(action, sender)) { + sender.sendMessage(join(spaces(), + text("Action", GRAY), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getReadableActionDataString()))), + text("has been issued to", GRAY), + asAdventure(bot.getDisplayName()) + )); + } + return true; + } + + @Contract(pure = true) + private @NotNull Supplier actionNodeCreator(ServerBotAction action) { + return () -> new LiteralNode(action.getName()) { + @Override + protected ArgumentBuilder compile() { + ArgumentBuilder builder = super.compile(); + + for (Map.Entry>>> entry : action.getArguments().entrySet()) { + List>> value = entry.getValue(); + ArgumentBuilder branchArgumentBuilder = null; + Command executor = context -> { + if (executor(new CommandContext(context), action)) { + return Command.SINGLE_SUCCESS; + } else { + return 0; + } + }; + + for (Pair> stringWrappedArgumentPair : value.reversed()) { + WrappedArgument argument = stringWrappedArgumentPair.getRight(); + if (branchArgumentBuilder == null) { + branchArgumentBuilder = argument.compile().executes(executor); + } else { + branchArgumentBuilder = argument.compile().then(branchArgumentBuilder); + if (argument.isOptional()) { + branchArgumentBuilder = branchArgumentBuilder.executes(executor); + } + } + } + + if (value.getFirst().getRight().isOptional()) { + builder = builder.executes(executor); + } + + if (branchArgumentBuilder != null) { + builder = builder.then(branchArgumentBuilder); + } + } + return builder; + } + }; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java new file mode 100644 index 00000000..79c2cfae --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java @@ -0,0 +1,131 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands.action; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.network.chat.Component; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.event.bot.BotActionStopEvent; +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.subcommands.ActionCommand; + +import java.util.HashSet; +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; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.*; + +public class StopCommand extends LiteralNode { + + public StopCommand() { + super("stop"); + children(StopIndexArgument::new); + children(StopAll::new); + } + + private static class StopIndexArgument extends ArgumentNode { + + protected StopIndexArgument() { + super("index", IntegerArgumentType.integer(0)); + } + + @Override + protected CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + if (bot == null) { + return Suggestions.empty(); + } + for (int i = 0; i < bot.getBotActions().size(); i++) { + ServerBotAction action = bot.getBotActions().get(i); + builder.suggest(String.valueOf(i), Component.literal(action.getName())); + } + return builder.buildFuture(); + } + + @Override + protected boolean execute(CommandContext context) { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + CommandSender sender = context.getSender(); + if (bot == null) { + return false; + } + int index = context.getArgument("index", Integer.class); + if (index < 0 || index >= bot.getBotActions().size()) { + sender.sendMessage(text("Invalid index.", RED)); + return false; + } + + ServerBotAction action = bot.getBotActions().get(index); + BotActionStopEvent event = new BotActionStopEvent( + bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender + ); + event.callEvent(); + if (!event.isCancelled()) { + action.stop(bot, BotActionStopEvent.Reason.COMMAND); + bot.getBotActions().remove(index); + sender.sendMessage(join(spaces(), + text("Already stopped", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("action", GRAY), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getReadableActionDataString()))) + )); + } else { + sender.sendMessage(text("Action stop cancelled by a plugin", RED)); + } + return true; + } + } + + private static class StopAll extends LiteralNode { + + public StopAll() { + super("all"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + if (bot == null) { + return false; + } + Set> canceled = new HashSet<>(); + Set> forRemoval = new HashSet<>(); + for (int i = 0; i < bot.getBotActions().size(); i++) { + ServerBotAction action = bot.getBotActions().get(i); + BotActionStopEvent event = new BotActionStopEvent( + bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, context.getSender() + ); + event.callEvent(); + if (!event.isCancelled()) { + forRemoval.add(action); + action.stop(bot, BotActionStopEvent.Reason.COMMAND); + } else { + canceled.add(action); + } + } + bot.getBotActions().removeAll(forRemoval); + if (canceled.isEmpty()) { + context.getSender().sendMessage(bot.getScoreboardName() + "'s action list cleared."); + } else { + context.getSender().sendMessage("already tried to clear" + bot.getScoreboardName() + "'s action list, but following actions' stop was canceled by plugin:"); + for (ServerBotAction action : canceled) { + context.getSender().sendMessage( + text(action.getName(), AQUA) + .hoverEvent(showText(text(action.getReadableActionDataString()))) + ); + } + } + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java new file mode 100644 index 00000000..30e6daf4 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java @@ -0,0 +1,27 @@ +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 values) { + return (context, builder) -> { + for (String s : values) { + builder.suggest(s); + } + }; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java new file mode 100644 index 00000000..145d39e3 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java @@ -0,0 +1,26 @@ +package org.leavesmc.leaves.neo_command.leaves; + +import net.minecraft.commands.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.neo_command.LiteralNode; +import org.leavesmc.leaves.neo_command.leaves.subcommands.ConfigCommand; + +public class LeavesCommand extends LiteralNode { + private static final String PERM_BASE = "bukkit.command.leaves"; + + public LeavesCommand() { + super("leaves_new"); + children(ConfigCommand::new); + } + + @Override + protected boolean requires(@NotNull CommandSourceStack source) { + return source.getSender().hasPermission(PERM_BASE); + } + + public static boolean hasPermission(@NotNull CommandSourceStack source, String subcommand) { + CommandSender sender = source.getSender(); + return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java similarity index 71% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java index 4d39b887..5ac52e9d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java @@ -1,11 +1,9 @@ -package org.leavesmc.leaves.neo_command.subcommands; +package org.leavesmc.leaves.neo_command.leaves.subcommands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.commands.CommandSourceStack; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,10 +13,14 @@ 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.leaves.LeavesCommand; import java.util.concurrent.CompletableFuture; +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.*; public class ConfigCommand extends LiteralNode { @@ -27,6 +29,11 @@ public ConfigCommand() { children(PathArgument::new); } + @Override + protected boolean requires(@NotNull CommandSourceStack source) { + return LeavesCommand.hasPermission(source, "config"); + } + private static class PathArgument extends ArgumentNode { public PathArgument() { @@ -43,7 +50,7 @@ protected CompletableFuture getSuggestions(@NotNull CommandContext context.getSender(), path.substring(dotIndex + 1), GlobalConfigManager.getVerifiedConfigSubPaths(path), - "bukkit.command.leaves.config" + "bukkit.command.leaves" ) .forEach(builder::suggest); return builder.buildFuture(); @@ -56,11 +63,11 @@ protected boolean execute(@NotNull CommandContext context) { if (verifiedConfig == null) { return false; } - context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(path, NamedTextColor.AQUA), - text("value is", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, AQUA), + text("value is", GRAY), + text(verifiedConfig.getString(), AQUA) )); return true; } @@ -69,10 +76,10 @@ protected boolean execute(@NotNull CommandContext context) { String path = context.getArgument(PathArgument.class); VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); if (verifiedConfig == null) { - context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(path, NamedTextColor.RED), - text("is Not Found.", NamedTextColor.GRAY) + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, RED), + text("is Not Found.", GRAY) )); return null; } @@ -113,31 +120,31 @@ protected boolean execute(@NotNull CommandContext context) { } try { verifiedConfig.set(value); - context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(path, NamedTextColor.AQUA), - text("changed to", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, AQUA), + text("changed to", GRAY), + text(verifiedConfig.getString(), AQUA) )); Bukkit.getOnlinePlayers() .stream() .filter(player -> player.hasPermission("leaves.command.config.notify") && player != context.getSender()) .forEach( - player -> player.sendMessage(Component.join(JoinConfiguration.spaces(), - text(context.getSender().getName() + ":", NamedTextColor.GRAY), - text("Config", NamedTextColor.GRAY), - text(path, NamedTextColor.AQUA), - text("changed to", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) + player -> player.sendMessage(join(spaces(), + text(context.getSender().getName() + ":", GRAY), + text("Config", GRAY), + text(path, AQUA), + text("changed to", GRAY), + text(verifiedConfig.getString(), AQUA) )) ); return true; } catch (IllegalArgumentException exception) { - context.getSender().sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(path, NamedTextColor.RED), - text("modify error by", NamedTextColor.GRAY), - text(exception.getMessage(), NamedTextColor.RED) + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, RED), + text("modify error by", GRAY), + text(exception.getMessage(), RED) )); return false; } From 285e70ac987165dccdc05794d52e10094f894a79 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sat, 23 Aug 2025 13:43:40 +0800 Subject: [PATCH 03/29] fix: fix bot action command --- .../bot/agent/actions/ServerBotAction.java | 17 +- .../bot/agent/actions/ServerLookAction.java | 10 ++ .../bot/agent/actions/ServerMountAction.java | 4 +- .../bot/agent/actions/ServerMoveAction.java | 30 +++- .../agent/actions/ServerRotationAction.java | 7 + .../agent/actions/ServerTimerBotAction.java | 16 +- .../bot/agent/actions/ServerUseBotAction.java | 7 + .../leaves/neo_command/CommandContext.java | 11 +- .../leaves/neo_command/CommandNode.java | 3 +- .../neo_command/CustomArgumentNode.java | 3 +- .../neo_command/CustomArgumentType.java | 2 +- .../leaves/neo_command/bot/BotArgument.java | 11 +- .../leaves/neo_command/bot/BotCommand.java | 6 +- .../bot/subcommands/ActionCommand.java | 11 +- .../bot/subcommands/CreateCommand.java | 152 ++++++++++++++++++ .../bot/subcommands/ListCommand.java | 98 +++++++++++ .../bot/subcommands/action/ListCommand.java | 20 ++- .../bot/subcommands/action/StartCommand.java | 33 ++-- .../bot/subcommands/action/StopCommand.java | 57 ++++--- 19 files changed, 413 insertions(+), 85 deletions(-) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java index c8e45d1e..73e77c56 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java @@ -59,12 +59,13 @@ public ServerBotAction(String name, Supplier creator) { public abstract Object asCraft(); - public List> provideReadableActionData() { - return new ArrayList<>(); + public void provideActionData(@NotNull ActionData data) { } - public String getReadableActionDataString() { - return provideReadableActionData().stream() + public String getActionDataString() { + ActionData data = new ActionData(new ArrayList<>()); + provideActionData(data); + return data.raw.stream() .map(pair -> pair.getLeft() + "=" + pair.getRight()) .reduce((a, b) -> a + ", " + b) .orElse("No arguments"); @@ -247,4 +248,12 @@ public void setOnSuccess(Consumer onSuccess) { public void setOnStop(Consumer onStop) { this.onStop = onStop; } + + public record ActionData( + List> raw + ) { + public void add(String key, String value) { + raw.add(Pair.of(key, value)); + } + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index 3b1eddea..539a0dfb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -98,6 +98,16 @@ public ServerPlayer getTarget() { return target; } + @Override + public void provideActionData(@NotNull ActionData data) { + super.provideActionData(data); + if (target != null) { + data.add("target", target.getName().getString()); + } else { + data.add("position", String.format("(%.2f, %.2f, %.2f)", pos.getX(), pos.getY(), pos.getZ())); + } + } + @Override public boolean doTick(@NotNull ServerBot bot) { if (target != null) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java index 3719200b..464bb761 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java @@ -22,8 +22,8 @@ public boolean doTick(@NotNull ServerBot bot) { Location center = bot.getBukkitEntity().getLocation(); List vehicles = center.getNearbyEntitiesByType( Vehicle.class, - 3, - vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 2 + 4, + vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 3 ).stream().sorted(Comparator.comparingDouble( (vehicle) -> center.distanceSquared(vehicle.getLocation()) )).toList(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index bd3c2f62..32104ea1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.bot.agent.actions; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; @@ -9,27 +10,36 @@ import org.leavesmc.leaves.neo_command.CommandContext; 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; public class ServerMoveAction extends ServerStateBotAction { - + private static final Map NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap( + it -> it.name, + it -> it + )); private MoveDirection direction = MoveDirection.FORWARD; public ServerMoveAction() { super("move", ServerMoveAction::new); this.addArgument("direction", StringArgumentType.word()) - .suggests(strings(Arrays.stream(MoveDirection.values()).map(MoveDirection::name).toList())); + .suggests(strings( + Arrays.stream(MoveDirection.values()) + .map((it) -> it.name) + .toList() + )); } @Override - public void loadCommand(@NotNull CommandContext context) { + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { String raw = context.getArgument("direction", String.class); - try { - this.direction = MoveDirection.valueOf(raw); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("Invalid move direction: " + raw); + MoveDirection direction = NAME_TO_DIRECTION.get(raw); + if (direction == null) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); } + this.direction = direction; } @Override @@ -54,6 +64,12 @@ public boolean doTick(@NotNull ServerBot bot) { return true; } + @Override + public void provideActionData(@NotNull ActionData data) { + super.provideActionData(data); + data.add("direction", direction.name); + } + public MoveDirection getDirection() { return direction; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 5cbc26aa..03c0e8d0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -56,6 +56,13 @@ public float getPitch() { return this.pitch; } + @Override + public void provideActionData(@NotNull ActionData data) { + super.provideActionData(data); + data.add("yaw", DF.format(this.yaw)); + data.add("pitch", DF.format(this.pitch)); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java index 81edbeb0..58f21986 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java @@ -1,12 +1,9 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.network.chat.Component; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.neo_command.CommandContext; -import java.util.ArrayList; -import java.util.List; import java.util.function.Supplier; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; @@ -35,12 +32,11 @@ public void loadCommand(@NotNull CommandContext context) { } @Override - public List> provideReadableActionData() { - return new ArrayList<>(List.of( - Pair.of("delay", String.valueOf(this.getStartDelayTick())), - Pair.of("interval", String.valueOf(this.getDoIntervalTick())), - Pair.of("do_number", String.valueOf(this.getDoNumber())), - Pair.of("remaining_do_number", String.valueOf(this.getDoNumberRemaining())) - )); + public void provideActionData(@NotNull ActionData data) { + super.provideActionData(data); + data.add("delay", String.valueOf(this.getStartDelayTick())); + data.add("interval", String.valueOf(this.getDoIntervalTick())); + data.add("do_number", String.valueOf(this.getDoNumber())); + data.add("remaining_do_number", String.valueOf(this.getDoNumberRemaining())); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java index a8292447..67657ec1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java @@ -97,6 +97,13 @@ private void increaseAlreadyUsedTick() { this.alreadyUsedTick++; } + @Override + public void provideActionData(@NotNull ActionData data) { + super.provideActionData(data); + data.add("use_timeout", String.valueOf(this.useTickTimeout)); + data.add("already_used_tick", String.valueOf(this.alreadyUsedTick)); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java index 2796ee16..1ff2c7f4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.context.ParsedCommandNode; import com.mojang.brigadier.context.StringRange; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; import net.minecraft.commands.CommandSourceStack; import org.bukkit.command.CommandSender; @@ -52,13 +53,13 @@ public CommandSender getSender() { } @SuppressWarnings("unchecked") - public @NotNull V getCustomArgument(final Class> nodeClass) { + public @NotNull V getCustomArgument(final Class> nodeClass) throws CommandSyntaxException { String name = getNameForNode(nodeClass); T raw = (T) source.getArgument(name, Object.class); return CustomArgumentNode.transform(nodeClass, raw); } - public @NotNull V getArgumentOrDefault(final Class> nodeClass, final V defaultValue) { + public V getArgumentOrDefault(final Class> nodeClass, final V defaultValue) { try { return getArgument(nodeClass); } catch (IllegalArgumentException e) { @@ -74,7 +75,7 @@ public V getArgumentOrDefault(final String name, final Class clazz, final } } - public V getCustomArgumentOrDefault(final Class> nodeClass, final V defaultValue) { + public V getCustomArgumentOrDefault(final Class> nodeClass, final V defaultValue) throws CommandSyntaxException { try { return getCustomArgument(nodeClass); } catch (IllegalArgumentException e) { @@ -121,4 +122,8 @@ public boolean hasNodes() { public boolean isForked() { return source.isForked(); } + + public com.mojang.brigadier.context.CommandContext getMojangContext() { + return source; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java index a4971c32..7c0da867 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.neo_command; import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.commands.CommandSourceStack; import org.jetbrains.annotations.NotNull; @@ -30,7 +31,7 @@ protected final void children(Supplier... childrenClasses protected abstract ArgumentBuilder compileBase(); - protected boolean execute(CommandContext context) { + protected boolean execute(CommandContext context) throws CommandSyntaxException { return true; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java index 9c7a5240..75fdc784 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java @@ -2,6 +2,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.commands.CommandSourceStack; import org.jetbrains.annotations.NotNull; @@ -17,7 +18,7 @@ protected CustomArgumentNode(String name, @NotNull CustomArgumentType argu TYPES.put(getClass(), argumentType); } - public static T transform(Class> nodeClass, B base) { + public static T transform(Class> nodeClass, B base) throws CommandSyntaxException { @SuppressWarnings("unchecked") CustomArgumentType type = (CustomArgumentType) TYPES.get(nodeClass); if (type == null) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java index f8c076b6..458ac711 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java @@ -11,7 +11,7 @@ public interface CustomArgumentType { ArgumentType getBaseArgumentType(); - T transform(B value); + T transform(B value) throws CommandSyntaxException; CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java index 08b88409..d65d41bf 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java @@ -2,8 +2,10 @@ import com.mojang.brigadier.arguments.ArgumentType; 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.minecraft.network.chat.Component; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.leavesmc.leaves.bot.ServerBot; @@ -22,16 +24,19 @@ public ArgumentType getBaseArgumentType() { } @Override - public ServerBot transform(String value) { + public ServerBot transform(String value) throws CommandSyntaxException { CraftBot craftBot = (CraftBot) Bukkit.getBotManager().getBot(value); if (craftBot == null) { - return null; + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), + Component.literal("Bot with name '" + value + "' does not exist") + ); } return craftBot.getHandle(); } @Override - public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { + public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { Collection bots = Bukkit.getBotManager().getBots(); if (bots.isEmpty()) { return builder diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java index 918ed621..f505d7a9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java @@ -6,6 +6,8 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.neo_command.LiteralNode; import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand; +import org.leavesmc.leaves.neo_command.bot.subcommands.CreateCommand; +import org.leavesmc.leaves.neo_command.bot.subcommands.ListCommand; public class BotCommand extends LiteralNode { private static final String PERM_BASE = "bukkit.command.bot"; @@ -13,7 +15,9 @@ public class BotCommand extends LiteralNode { public BotCommand() { super("bot_neo"); this.children( - ActionCommand::new + ActionCommand::new, + ListCommand::new, + CreateCommand::new ); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java index ad349d11..81591c28 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java @@ -1,8 +1,8 @@ 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.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.neo_command.CommandContext; import org.leavesmc.leaves.neo_command.CustomArgumentNode; @@ -35,13 +35,8 @@ protected BotArgument() { ); } - public static @Nullable ServerBot getBot(@NotNull CommandContext context) { - try { - return context.getCustomArgument(BotArgument.class); - } catch (IllegalArgumentException e) { - context.getSender().sendMessage("This bot does not exist."); - return null; - } + public static @NotNull ServerBot getBot(@NotNull CommandContext context) throws CommandSyntaxException { + return context.getCustomArgument(BotArgument.class); } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java new file mode 100644 index 00000000..5fecbd06 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java @@ -0,0 +1,152 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.arguments.DimensionArgument; +import net.minecraft.commands.arguments.coordinates.Coordinates; +import net.minecraft.commands.arguments.coordinates.Vec3Argument; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.BotCreateState; +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 static net.kyori.adventure.text.Component.text; +import static net.minecraft.commands.arguments.DimensionArgument.getDimension; + +public class CreateCommand extends LiteralNode { + + public CreateCommand() { + super("create"); + children(NameArgument::new); + } + + protected static boolean handleCreateCommand(@NotNull CommandContext context) throws CommandSyntaxException { + CommandSender sender = context.getSender(); + + String name = context.getArgument(NameArgument.class); + if (!canCreate(sender, name)) { + return false; + } + String skinName = context.getArgumentOrDefault(SkinNameArgument.class, name); + + World world; + try { + world = getDimension(context.getMojangContext(), "world").getWorld(); + } catch (IllegalArgumentException e) { + if (!(sender instanceof Entity entity)) { + sender.sendMessage(text("Must specify world and location when executed by console", NamedTextColor.RED)); + return false; + } + world = entity.getWorld(); + } + + Location location = Bukkit.getWorlds().getFirst().getSpawnLocation(); + Coordinates coords = context.getArgumentOrDefault(LocationArgument.class, null); + if (coords != null) { + Vec3 vec3 = coords.getPosition(context.getSource()); + location = new Location(world, vec3.x, vec3.y, vec3.z); + } else if (sender instanceof Entity entity) { + location = entity.getLocation(); + } + + BotCreateState + .builder(name, location) + .createReason(BotCreateEvent.CreateReason.COMMAND) + .skinName(skinName) + .creator(sender) + .spawnWithSkin(null); + + return true; + } + + private static boolean canCreate(CommandSender sender, @NotNull String name) { + BotList botList = BotList.INSTANCE; + if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { + sender.sendMessage(text("This name is illegal", NamedTextColor.RED)); + return false; + } + + if (Bukkit.getPlayerExact(name) != null || botList.getBotByName(name) != null) { + sender.sendMessage(text("This bot is already in server", NamedTextColor.RED)); + return false; + } + + if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { + sender.sendMessage(text("This name is not allowed", NamedTextColor.RED)); + return false; + } + + if (botList.bots.size() >= LeavesConfig.modify.fakeplayer.limit) { + sender.sendMessage(text("Bot number limit exceeded", NamedTextColor.RED)); + return false; + } + + return true; + } + + private static class NameArgument extends ArgumentNode { + + public NameArgument() { + super("name", StringArgumentType.word()); + children(SkinNameArgument::new); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return handleCreateCommand(context); + } + } + + private static class SkinNameArgument extends ArgumentNode { + + public SkinNameArgument() { + super("skin_name", StringArgumentType.word()); + children(WorldArgument::new); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return handleCreateCommand(context); + } + + } + + private static class WorldArgument extends ArgumentNode { + + public WorldArgument() { + super("world", DimensionArgument.dimension()); + children(LocationArgument::new); + } + + @Override + protected boolean requires(@NotNull CommandSourceStack source) { + return source.getSender() instanceof ConsoleCommandSender; + } + } + + private static class LocationArgument extends ArgumentNode { + + public LocationArgument() { + super("location", Vec3Argument.vec3(true)); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return handleCreateCommand(context); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java new file mode 100644 index 00000000..9a43293f --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java @@ -0,0 +1,98 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.Component; +import net.minecraft.commands.arguments.DimensionArgument; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.player.Player; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.CraftWorld; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +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.LiteralNode; + +import java.util.List; +import java.util.Objects; + +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.noSeparators; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.minecraft.commands.arguments.DimensionArgument.getDimension; + + +public class ListCommand extends LiteralNode { + + public ListCommand() { + super("list"); + children(WorldArgument::new); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + Component msg = Bukkit.getWorlds().stream() + .map(ListCommand::getBotListMessage) + .filter(Objects::nonNull) + .reduce((a, b) -> a.append(text("\n")).append(b)) + .orElseGet(() -> text("No bots on the server", GRAY)); + context.getSender().sendMessage(join(noSeparators(), + text("Total bot number: ", GRAY), + text(BotList.INSTANCE.bots.size(), AQUA).hoverEvent(showText(text("current bot count"))), + text("/", GRAY), + text(LeavesConfig.modify.fakeplayer.limit, AQUA).hoverEvent(showText(text("bot count limit"))) + )); + context.getSender().sendMessage(msg); + return true; + } + + protected static @Nullable Component getBotListMessage(@NotNull World world) { + BotList botList = BotList.INSTANCE; + List botsInLevel = botList.bots.stream() + .filter((bot) -> bot.getBukkitEntity().getWorld().equals(world)) + .toList(); + if (botsInLevel.isEmpty()) { + return null; + } + Component botsMsg = botsInLevel.stream() + .map(Player::getDisplayName) + .map(PaperAdventure::asAdventure) + .reduce((a, b) -> a.append(text(", ", GRAY)).append(b)) + .get(); + String worldLocation = ((CraftWorld) world).getHandle().dimension().location().toString(); + return join(noSeparators(), + text(world.getName(), AQUA).hoverEvent(showText(text(worldLocation))), + text(" (" + botsInLevel.size() + ")\n", GRAY), + botsMsg + ); + } + + private static class WorldArgument extends ArgumentNode { + + protected WorldArgument() { + super("world", DimensionArgument.dimension()); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + ServerLevel dimension = getDimension(context.getMojangContext(), "world"); + Component botListMessage = getBotListMessage(dimension.getWorld()); + CommandSender sender = context.getSender(); + if (botListMessage == null) { + sender.sendMessage(text("No bots in that world", RED)); + } else { + sender.sendMessage(text("Bot in ").append(botListMessage)); + } + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java index 3a32a4b7..754309e0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java @@ -1,5 +1,7 @@ package org.leavesmc.leaves.neo_command.bot.subcommands.action; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; @@ -9,6 +11,7 @@ import java.util.List; +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; @@ -23,24 +26,25 @@ public ListCommand() { } @Override - protected boolean execute(@NotNull CommandContext context) { + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { ServerBot bot = ActionCommand.BotArgument.getBot(context); - if (bot == null) { - return false; - } + CommandSender sender = context.getSender(); List> actions = bot.getBotActions(); if (actions.isEmpty()) { - context.getSender().sendMessage("This bot has no active actions"); + sender.sendMessage(text("This bot has no active actions", GRAY)); return true; } - context.getSender().sendMessage(bot.getScoreboardName() + "'s action list:"); + sender.sendMessage( + asAdventure(bot.getDisplayName()) + .append(text("'s action list:", GRAY)) + ); for (int i = 0; i < actions.size(); i++) { ServerBotAction action = actions.get(i); - context.getSender().sendMessage(join(spaces(), + sender.sendMessage(join(spaces(), text(i, GRAY), - text(action.getName(), AQUA).hoverEvent(showText(text(action.getReadableActionDataString()))) + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) )); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java index 0ac8073d..ea1a76ce 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java @@ -38,21 +38,20 @@ public StartCommand() { .forEach(this::children); } - private boolean executor(CommandContext context, @NotNull ServerBotAction action) throws CommandSyntaxException { + private boolean handleStartCommand(CommandContext context, @NotNull ServerBotAction action) throws CommandSyntaxException { ServerBot bot = getBot(context); CommandSender sender = context.getSender(); - if (bot == null) { - return false; - } + action.loadCommand(context); if (bot.addBotAction(action, sender)) { sender.sendMessage(join(spaces(), text("Action", GRAY), - text(action.getName(), AQUA).hoverEvent(showText(text(action.getReadableActionDataString()))), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))), text("has been issued to", GRAY), asAdventure(bot.getDisplayName()) )); } + return true; } @@ -63,16 +62,17 @@ private boolean executor(CommandContext context, @NotNull ServerBotAction act protected ArgumentBuilder compile() { ArgumentBuilder builder = super.compile(); - for (Map.Entry>>> entry : action.getArguments().entrySet()) { + Map>>> arguments = action.getArguments(); + Command executor = context -> { + if (handleStartCommand(new CommandContext(context), action)) { + return Command.SINGLE_SUCCESS; + } else { + return 0; + } + }; + for (Map.Entry>>> entry : arguments.entrySet()) { List>> value = entry.getValue(); ArgumentBuilder branchArgumentBuilder = null; - Command executor = context -> { - if (executor(new CommandContext(context), action)) { - return Command.SINGLE_SUCCESS; - } else { - return 0; - } - }; for (Pair> stringWrappedArgumentPair : value.reversed()) { WrappedArgument argument = stringWrappedArgumentPair.getRight(); @@ -86,7 +86,7 @@ private boolean executor(CommandContext context, @NotNull ServerBotAction act } } - if (value.getFirst().getRight().isOptional()) { + if (value.getFirst().getRight().isOptional() || value.isEmpty()) { builder = builder.executes(executor); } @@ -94,6 +94,11 @@ private boolean executor(CommandContext context, @NotNull ServerBotAction act builder = builder.then(branchArgumentBuilder); } } + + if (arguments.isEmpty()) { + builder = builder.executes(executor); + } + return builder; } }; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java index 79c2cfae..e23a077f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.neo_command.bot.subcommands.action; import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.network.chat.Component; @@ -15,6 +16,7 @@ import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -40,29 +42,29 @@ protected StopIndexArgument() { } @Override - protected CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { + protected CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { ServerBot bot = ActionCommand.BotArgument.getBot(context); - if (bot == null) { - return Suggestions.empty(); - } + for (int i = 0; i < bot.getBotActions().size(); i++) { ServerBotAction action = bot.getBotActions().get(i); builder.suggest(String.valueOf(i), Component.literal(action.getName())); } + return builder.buildFuture(); } @Override - protected boolean execute(CommandContext context) { + protected boolean execute(CommandContext context) throws CommandSyntaxException { ServerBot bot = ActionCommand.BotArgument.getBot(context); CommandSender sender = context.getSender(); - if (bot == null) { - return false; + + int index = context.getArgument(StopIndexArgument.class); + int maxIndex = bot.getBotActions().size() - 1; + if (maxIndex < 0) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); } - int index = context.getArgument("index", Integer.class); - if (index < 0 || index >= bot.getBotActions().size()) { - sender.sendMessage(text("Invalid index.", RED)); - return false; + if (index > maxIndex) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.integerTooHigh().create(index, maxIndex); } ServerBotAction action = bot.getBotActions().get(index); @@ -77,7 +79,7 @@ protected boolean execute(CommandContext context) { text("Already stopped", GRAY), asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), text("action", GRAY), - text(action.getName(), AQUA).hoverEvent(showText(text(action.getReadableActionDataString()))) + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) )); } else { sender.sendMessage(text("Action stop cancelled by a plugin", RED)); @@ -93,17 +95,21 @@ public StopAll() { } @Override - protected boolean execute(@NotNull CommandContext context) { + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { ServerBot bot = ActionCommand.BotArgument.getBot(context); - if (bot == null) { - return false; + + List> actions = bot.getBotActions(); + CommandSender sender = context.getSender(); + if (actions.isEmpty()) { + sender.sendMessage(text("This bot has no active actions", GRAY)); + return true; } + Set> canceled = new HashSet<>(); Set> forRemoval = new HashSet<>(); - for (int i = 0; i < bot.getBotActions().size(); i++) { - ServerBotAction action = bot.getBotActions().get(i); + for (ServerBotAction action : actions) { BotActionStopEvent event = new BotActionStopEvent( - bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, context.getSender() + bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender ); event.callEvent(); if (!event.isCancelled()) { @@ -114,14 +120,21 @@ protected boolean execute(@NotNull CommandContext context) { } } bot.getBotActions().removeAll(forRemoval); + if (canceled.isEmpty()) { - context.getSender().sendMessage(bot.getScoreboardName() + "'s action list cleared."); + sender.sendMessage(join(spaces(), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("'s action list cleared", GRAY) + )); } else { - context.getSender().sendMessage("already tried to clear" + bot.getScoreboardName() + "'s action list, but following actions' stop was canceled by plugin:"); + sender.sendMessage(join(spaces(), + text("Tried to clear", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("'s action list, but following actions' stop was canceled by plugin:", GRAY) + )); for (ServerBotAction action : canceled) { context.getSender().sendMessage( - text(action.getName(), AQUA) - .hoverEvent(showText(text(action.getReadableActionDataString()))) + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) ); } } From eb86035885452a5b13de85b00bcf37637556f1f6 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sat, 23 Aug 2025 16:26:23 +0800 Subject: [PATCH 04/29] feat: finish perms system, fix bugs --- .../org/leavesmc/leaves/LeavesConfig.java | 60 +++++++- .../bot/agent/actions/ServerMoveAction.java | 2 +- .../agent/actions/ServerTimerBotAction.java | 2 +- .../leaves/neo_command/ArgumentNode.java | 23 +++ .../leaves/neo_command/CommandNode.java | 6 +- .../leaves/neo_command/CommandUtils.java | 135 ++++++++++++++++++ .../leaves/neo_command/LeavesCommands.java | 15 -- .../leaves/neo_command/LiteralNode.java | 16 ++- .../leaves/neo_command/bot/BotArgument.java | 2 +- .../leaves/neo_command/bot/BotCommand.java | 38 ++++- .../leaves/neo_command/bot/BotSubcommand.java | 17 +++ .../bot/subcommands/ActionCommand.java | 10 +- .../bot/subcommands/ConfigCommand.java | 10 ++ .../bot/subcommands/CreateCommand.java | 6 +- .../bot/subcommands/ListCommand.java | 4 +- .../bot/subcommands/LoadCommand.java | 80 +++++++++++ .../bot/subcommands/SaveCommand.java | 57 ++++++++ .../leaves/ArgumentSuggestions.java | 27 ---- .../neo_command/leaves/LeavesCommand.java | 25 +++- .../leaves/subcommands/ConfigCommand.java | 14 +- 20 files changed, 465 insertions(+), 84 deletions(-) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index f2e7325a..289fbdd1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -6,6 +6,7 @@ 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.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 static void init(final @NotNull File file) { 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 @@ private static class FakeplayerValidator extends BooleanConfigValidator { 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 void verify(Double old, Double value) throws IllegalArgumentException { @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; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 32104ea1..3dc723bc 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -13,7 +13,7 @@ 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 { private static final Map NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap( diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java index 58f21986..6cea5c42 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java @@ -7,7 +7,7 @@ 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> extends ServerBotAction { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java index 8f9aea04..0f70d0a0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java @@ -8,7 +8,10 @@ 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 extends CommandNode { @@ -36,4 +39,24 @@ protected CompletableFuture getSuggestions(final CommandContext con 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 values) { + return (context, builder) -> { + for (String s : values) { + builder.suggest(s); + } + }; + } + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java index 7c0da867..41859e21 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java @@ -35,10 +35,14 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException return true; } - protected boolean requires(CommandSourceStack source) { + public boolean requires(CommandSourceStack source) { return true; } + public String getName() { + return this.name; + } + protected ArgumentBuilder compile() { ArgumentBuilder builder = compileBase(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java new file mode 100644 index 00000000..d6a04cf0 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java @@ -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 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 getListClosestMatchingLast( + final String last, + final Collection collection + ) { + if (collection.isEmpty()) { + return Collections.emptyList(); + } + + ArrayList 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 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 Wikipedia: Damerau–Levenshtein distance + * + * @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 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); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java deleted file mode 100644 index b16cda68..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LeavesCommands.java +++ /dev/null @@ -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 dispatcher = MinecraftServer.getServer().getCommands().getDispatcher(); - new LeavesCommand().register(dispatcher); - new BotCommand().register(dispatcher); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java index 0fa870ef..94eb69a9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java @@ -5,7 +5,7 @@ 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 @@ protected LiteralNode(String name) { } @SuppressWarnings("unchecked") - public void register(@NotNull CommandDispatcher dispatcher) { - dispatcher.register((LiteralArgumentBuilder) compile()); + public void register() { + MinecraftServer.getServer() + .getCommands() + .getDispatcher() + .register((LiteralArgumentBuilder) compile()); + } + + public void unregister() { + CommandDispatcher dispatcher = MinecraftServer.getServer() + .getCommands() + .getDispatcher(); + dispatcher.getRoot().removeCommand(name); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java index d65d41bf..ee16c072 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java @@ -20,7 +20,7 @@ public class BotArgument implements CustomArgumentType { @Override public ArgumentType getBaseArgumentType() { - return StringArgumentType.string(); + return StringArgumentType.word(); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java index f505d7a9..ef72ef89 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java @@ -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 compile() { + List permissions = new ArrayList<>(); + permissions.add(PERM_BASE); + permissions.addAll(this.children.stream().map(CommandNode::getName).toList()); + CommandUtils.registerPermissions(permissions); + return super.compile(); + } + + @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 CommandSourceStack source, String subcommand) { - CommandSender sender = source.getSender(); + public static boolean hasPermission(@NotNull CommandSender sender, String subcommand) { return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java new file mode 100644 index 00000000..10998310 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java @@ -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); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java index 81591c28..32bc4a94 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java @@ -3,16 +3,16 @@ 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 ActionCommand() { } @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 { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java new file mode 100644 index 00000000..051bb3b1 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java @@ -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"); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java index 5fecbd06..da03268b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java @@ -22,12 +22,12 @@ 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 WorldArgument() { } @Override - protected boolean requires(@NotNull CommandSourceStack source) { + public boolean requires(@NotNull CommandSourceStack source) { return source.getSender() instanceof ConsoleCommandSender; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java index 9a43293f..00952077 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java @@ -18,7 +18,7 @@ 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.minecraft.commands.arguments.DimensionArgument.getDimension; -public class ListCommand extends LiteralNode { +public class ListCommand extends BotSubcommand { public ListCommand() { super("list"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java new file mode 100644 index 00000000..aebc4efa --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java @@ -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 { + + 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 getSuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { + BotList botList = BotList.INSTANCE; + Set bots = botList.getSavedBotList().keySet(); + if (bots.isEmpty()) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("There are no bots saved before, save one first.")) + .buildFuture(); + } + bots.forEach(builder::suggest); + return builder.buildFuture(); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java new file mode 100644 index 00000000..f3a32bd8 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java @@ -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 { + + 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; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java deleted file mode 100644 index 30e6daf4..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/ArgumentSuggestions.java +++ /dev/null @@ -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 values) { - return (context, builder) -> { - for (String s : values) { - builder.suggest(s); - } - }; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java index 145d39e3..8da87769 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java @@ -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 compile() { + List permissions = new ArrayList<>(); + permissions.add(PERM_BASE); + permissions.addAll(this.children.stream().map(CommandNode::getName).toList()); + CommandUtils.registerPermissions(permissions); + return super.compile(); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return children.stream().anyMatch(child -> child.requires(source)); } - public static boolean hasPermission(@NotNull CommandSourceStack source, String subcommand) { - CommandSender sender = source.getSender(); + public static boolean hasPermission(@NotNull CommandSender sender, String subcommand) { return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java index 5ac52e9d..ad547038 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java @@ -21,6 +21,7 @@ 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 ConfigCommand() { } @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 { @@ -46,13 +47,10 @@ protected CompletableFuture getSuggestions(@NotNull CommandContext 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(); } From 67e128db95b6fc167ca4a0f830b22f268e37b029 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 10:11:31 +0800 Subject: [PATCH 05/29] feat: add bot config command --- .../org/leavesmc/leaves/bot/BotCommand.java | 3 +- .../org/leavesmc/leaves/bot/ServerBot.java | 40 ++-- .../leaves/bot/agent/AbstractBotConfig.java | 67 ------ .../leavesmc/leaves/bot/agent/Actions.java | 12 +- .../leavesmc/leaves/bot/agent/Configs.java | 62 ++--- ...rBotAction.java => AbstractBotAction.java} | 4 +- .../agent/actions/AbstractStateBotAction.java | 11 + ...ction.java => AbstractTimerBotAction.java} | 4 +- ...tAction.java => AbstractUseBotAction.java} | 4 +- .../bot/agent/actions/ServerAttackAction.java | 2 +- .../agent/actions/ServerBreakBlockAction.java | 2 +- .../bot/agent/actions/ServerDropAction.java | 2 +- .../bot/agent/actions/ServerFishAction.java | 2 +- .../bot/agent/actions/ServerJumpAction.java | 2 +- .../bot/agent/actions/ServerLookAction.java | 2 +- .../bot/agent/actions/ServerMountAction.java | 2 +- .../bot/agent/actions/ServerMoveAction.java | 2 +- .../agent/actions/ServerRotationAction.java | 2 +- .../bot/agent/actions/ServerSneakAction.java | 2 +- .../agent/actions/ServerStateBotAction.java | 11 - .../bot/agent/actions/ServerSwapAction.java | 2 +- .../bot/agent/actions/ServerSwimAction.java | 2 +- .../agent/actions/ServerUseItemAction.java | 2 +- .../actions/ServerUseItemAutoAction.java | 2 +- .../actions/ServerUseItemOffhandAction.java | 2 +- .../agent/actions/ServerUseItemOnAction.java | 2 +- .../actions/ServerUseItemOnOffhandAction.java | 2 +- .../agent/actions/ServerUseItemToAction.java | 2 +- .../actions/ServerUseItemToOffhandAction.java | 2 +- .../bot/agent/configs/AbstractBotConfig.java | 102 ++++++++ .../agent/configs/AlwaysSendDataConfig.java | 23 +- .../bot/agent/configs/LocatorBarConfig.java | 25 +- .../configs/SimulationDistanceConfig.java | 36 +-- .../bot/agent/configs/SkipSleepConfig.java | 22 +- .../bot/agent/configs/SpawnPhantomConfig.java | 29 ++- .../bot/agent/configs/TickTypeConfig.java | 42 ++-- .../bot/subcommands/BotConfigCommand.java | 220 +++++++++--------- .../leavesmc/leaves/entity/bot/CraftBot.java | 4 +- .../leaves/entity/bot/CraftBotManager.java | 4 +- .../entity/bot/actions/CraftBotAction.java | 6 +- .../bot/actions/CraftTimerBotAction.java | 4 +- .../leaves/neo_command/CommandContext.java | 12 + .../bot/subcommands/ActionCommand.java | 2 +- .../bot/subcommands/ConfigCommand.java | 96 ++++++++ .../bot/subcommands/action/ListCommand.java | 6 +- .../bot/subcommands/action/StartCommand.java | 87 +++---- .../bot/subcommands/action/StopCommand.java | 16 +- .../leaves/subcommands/ConfigCommand.java | 6 +- 48 files changed, 574 insertions(+), 424 deletions(-) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java rename leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/{ServerBotAction.java => AbstractBotAction.java} (98%) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java rename leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/{ServerTimerBotAction.java => AbstractTimerBotAction.java} (89%) rename leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/{ServerUseBotAction.java => AbstractUseBotAction.java} (95%) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java index 1a40ec37..32b5482d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java @@ -2,7 +2,6 @@ import net.minecraft.Util; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.subcommands.BotConfigCommand; import org.leavesmc.leaves.bot.subcommands.BotCreateCommand; import org.leavesmc.leaves.bot.subcommands.BotListCommand; import org.leavesmc.leaves.bot.subcommands.BotLoadCommand; @@ -24,7 +23,7 @@ public class BotCommand extends LeavesRootCommand { commands.put(Set.of("create"), new BotCreateCommand()); commands.put(Set.of("remove"), new BotRemoveCommand()); // commands.put(Set.of("action"), new BotActionCommand()); - commands.put(Set.of("config"), new BotConfigCommand()); +// commands.put(Set.of("config"), new BotConfigCommand()); commands.put(Set.of("save"), new BotSaveCommand()); commands.put(Set.of("load"), new BotLoadCommand()); commands.put(Set.of("list"), new BotListCommand()); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java index 159a0384..faa48bf7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java @@ -59,10 +59,10 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.Configs; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; +import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; import org.leavesmc.leaves.entity.bot.CraftBot; import org.leavesmc.leaves.event.bot.BotActionScheduleEvent; import org.leavesmc.leaves.event.bot.BotCreateEvent; @@ -83,8 +83,8 @@ public class ServerBot extends ServerPlayer { - private final List> actions; - private final Map, AbstractBotConfig> configs; + private final List> actions; + private final Map> configs; public boolean resume = false; public BotCreateState createState; @@ -106,9 +106,9 @@ public ServerBot(MinecraftServer server, ServerLevel world, GameProfile profile) this.gameMode = new ServerBotGameMode(this); this.actions = new ArrayList<>(); - ImmutableMap.Builder, AbstractBotConfig> configBuilder = ImmutableMap.builder(); - for (Configs config : Configs.getConfigs()) { - configBuilder.put(config, config.createConfig(this)); + ImmutableMap.Builder> configBuilder = ImmutableMap.builder(); + for (AbstractBotConfig config : Configs.getConfigs()) { + configBuilder.put(config.getName(), config.create().setBot(this)); } this.configs = configBuilder.build(); @@ -388,14 +388,14 @@ public void addAdditionalSaveData(@NotNull ValueOutput nbt) { if (!this.actions.isEmpty()) { ValueOutput.TypedOutputList actionNbt = nbt.list("actions", CompoundTag.CODEC); - for (ServerBotAction action : this.actions) { + for (AbstractBotAction action : this.actions) { actionNbt.add(action.save(new CompoundTag())); } } if (!this.configs.isEmpty()) { ValueOutput.TypedOutputList configNbt = nbt.list("configs", CompoundTag.CODEC); - for (AbstractBotConfig config : this.configs.values()) { + for (AbstractBotConfig config : this.configs.values()) { configNbt.add(config.save(new CompoundTag())); } } @@ -428,9 +428,9 @@ public void readAdditionalSaveData(@NotNull ValueInput nbt) { if (nbt.list("actions", CompoundTag.CODEC).isPresent()) { ValueInput.TypedInputList actionNbt = nbt.list("actions", CompoundTag.CODEC).orElseThrow(); actionNbt.forEach(actionTag -> { - ServerBotAction action = Actions.getForName(actionTag.getString("actionName").orElseThrow()); + AbstractBotAction action = Actions.getForName(actionTag.getString("actionName").orElseThrow()); if (action != null) { - ServerBotAction newAction = action.create(); + AbstractBotAction newAction = action.create(); newAction.load(actionTag); this.actions.add(newAction); } @@ -440,9 +440,9 @@ public void readAdditionalSaveData(@NotNull ValueInput nbt) { if (nbt.list("configs", CompoundTag.CODEC).isPresent()) { ValueInput.TypedInputList configNbt = nbt.list("configs", CompoundTag.CODEC).orElseThrow(); for (CompoundTag configTag : configNbt) { - Configs configKey = Configs.getConfig(configTag.getString("configName").orElseThrow()); - if (configKey != null) { - this.configs.get(configKey).load(configTag); + AbstractBotConfig config = Configs.getConfig(configTag.getString("configName").orElseThrow()); + if (config != null) { + config.load(configTag); } } } @@ -640,11 +640,11 @@ public void dropAll(boolean death) { private void runAction() { if (LeavesConfig.modify.fakeplayer.canUseAction) { this.actions.forEach(action -> action.tryTick(this)); - this.actions.removeIf(ServerBotAction::isCancelled); + this.actions.removeIf(AbstractBotAction::isCancelled); } } - public boolean addBotAction(ServerBotAction action, CommandSender sender) { + public boolean addBotAction(AbstractBotAction action, CommandSender sender) { if (!LeavesConfig.modify.fakeplayer.canUseAction) { return false; } @@ -658,7 +658,7 @@ public boolean addBotAction(ServerBotAction action, CommandSender sender) { return true; } - public List> getBotActions() { + public List> getBotActions() { return actions; } @@ -669,11 +669,11 @@ public ServerStatsCounter getStats() { } @SuppressWarnings("unchecked") - public AbstractBotConfig getConfig(Configs config) { - return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config)); + public > AbstractBotConfig getConfig(@NotNull AbstractBotConfig config) { + return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config.getName())); } - public E getConfigValue(Configs config) { + public > O getConfigValue(@NotNull AbstractBotConfig config) { return this.getConfig(config).getValue(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java deleted file mode 100644 index 4d85f5be..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.leavesmc.leaves.bot.agent; - -import net.minecraft.nbt.CompoundTag; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; - -import java.util.List; - -public abstract class AbstractBotConfig { - - private final String name; - private final CommandArgument argument; - - protected ServerBot bot; - - public AbstractBotConfig(String name, CommandArgument argument) { - this.name = name; - this.argument = argument; - } - - public AbstractBotConfig setBot(ServerBot bot) { - this.bot = bot; - return this; - } - - public abstract E getValue(); - - public abstract void setValue(E value) throws IllegalArgumentException; - - @SuppressWarnings("unchecked") - public void setFromCommand(@NotNull CommandArgumentResult result) throws IllegalArgumentException { - if (argument == CommandArgument.EMPTY) { - throw new IllegalArgumentException("No argument for " + this.getName()); - } - try { - this.setValue((E) result.read(argument.getArgumentTypes().getFirst().getType())); - } catch (ClassCastException e) { - throw new IllegalArgumentException("Invalid argument type for " + this.getName() + ": " + e.getMessage()); - } - } - - public List getMessage() { - return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + ": " + this.getValue()); - } - - public List getChangeMessage() { - return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + " changed: " + this.getValue()); - } - - public String getName() { - return name; - } - - public CommandArgument getArgument() { - return argument; - } - - @NotNull - public CompoundTag save(@NotNull CompoundTag nbt) { - nbt.putString("configName", this.name); - return nbt; - } - - public abstract void load(@NotNull CompoundTag nbt); -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index 6b9cabc7..9142fa14 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -13,8 +13,8 @@ public class Actions { - private static final Map> actionsByName = new HashMap<>(); - private static final Map, ServerBotAction> actionsByClass = new HashMap<>(); + private static final Map> actionsByName = new HashMap<>(); + private static final Map, AbstractBotAction> actionsByClass = new HashMap<>(); public static void registerAll() { register(new ServerAttackAction(), AttackAction.class); @@ -38,7 +38,7 @@ public static void registerAll() { register(new ServerSwapAction(), SwapAction.class); } - public static boolean register(@NotNull ServerBotAction action, Class> type) { + public static boolean register(@NotNull AbstractBotAction action, Class> type) { if (!actionsByName.containsKey(action.getName())) { actionsByName.put(action.getName(), action); actionsByClass.put(type, action); @@ -54,7 +54,7 @@ public static boolean unregister(@NotNull String name) { @NotNull @Contract(pure = true) - public static Collection> getAll() { + public static Collection> getAll() { return actionsByName.values(); } @@ -64,12 +64,12 @@ public static Set getNames() { } @Nullable - public static ServerBotAction getForName(String name) { + public static AbstractBotAction getForName(String name) { return actionsByName.get(name); } @Nullable - public static ServerBotAction getForClass(@NotNull Class type) { + public static AbstractBotAction getForClass(@NotNull Class type) { return actionsByClass.get(type); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java index 8608a262..da53cc96 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java @@ -3,7 +3,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; import org.leavesmc.leaves.bot.agent.configs.AlwaysSendDataConfig; import org.leavesmc.leaves.bot.agent.configs.LocatorBarConfig; import org.leavesmc.leaves.bot.agent.configs.SimulationDistanceConfig; @@ -14,57 +14,35 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.function.Supplier; -@SuppressWarnings("unused") -public class Configs { +@SuppressWarnings({"unused"}) +public class Configs { + private static final Map, AbstractBotConfig> configs = new HashMap<>(); - private static final Map> configs = new HashMap<>(); - - public static final Configs SKIP_SLEEP = register(SkipSleepConfig.class, SkipSleepConfig::new); - public static final Configs ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new); - public static final Configs SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new); - public static final Configs SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new); - public static final Configs TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new); - public static final Configs ENABLE_LOCATOR_BAR = register(LocatorBarConfig.class, LocatorBarConfig::new); - - private final Class> configClass; - private final Supplier> configCreator; - - private Configs(Class> configClass, Supplier> configCreator) { - this.configClass = configClass; - this.configCreator = configCreator; - } - - public Class> getConfigClass() { - return configClass; - } - - public AbstractBotConfig createConfig(ServerBot bot) { - return configCreator.get().setBot(bot); - } + public static final SkipSleepConfig SKIP_SLEEP = register(new SkipSleepConfig()); + public static final AlwaysSendDataConfig ALWAYS_SEND_DATA = register(new AlwaysSendDataConfig()); + public static final SpawnPhantomConfig SPAWN_PHANTOM = register(new SpawnPhantomConfig()); + public static final SimulationDistanceConfig SIMULATION_DISTANCE = register(new SimulationDistanceConfig()); + public static final TickTypeConfig TICK_TYPE = register(new TickTypeConfig()); + public static final LocatorBarConfig ENABLE_LOCATOR_BAR = register(new LocatorBarConfig()); @Nullable - public static Configs getConfig(String name) { - return configs.get(name); + public static AbstractBotConfig getConfig(String name) { + return configs.values().stream() + .filter(config -> config.getName().equals(name)) + .findFirst() + .orElse(null); } @NotNull @Contract(pure = true) - public static Collection> getConfigs() { + public static Collection> getConfigs() { return configs.values(); } - @NotNull - @Contract(pure = true) - public static Collection getConfigNames() { - return configs.keySet(); - } - - @NotNull - private static Configs register(Class> configClass, Supplier> configCreator) { - Configs config = new Configs<>(configClass, configCreator); - configs.put(config.createConfig(null).getName(), config); - return config; + @SuppressWarnings("unchecked") + private static > @NotNull E register(AbstractBotConfig instance) { + configs.put(instance.getClass(), instance); + return (E) instance; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java similarity index 98% rename from leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java rename to leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index 73e77c56..86286b94 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -23,7 +23,7 @@ import java.util.function.Supplier; @SuppressWarnings("unchecked") -public abstract class ServerBotAction> { +public abstract class AbstractBotAction> { private final String name; private final Map>>> arguments; @@ -43,7 +43,7 @@ public abstract class ServerBotAction> { private Consumer onSuccess; private Consumer onStop; - public ServerBotAction(String name, Supplier creator) { + public AbstractBotAction(String name, Supplier creator) { this.name = name; this.uuid = UUID.randomUUID(); this.creator = creator; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java new file mode 100644 index 00000000..6a6007fc --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java @@ -0,0 +1,11 @@ +package org.leavesmc.leaves.bot.agent.actions; + +import java.util.function.Supplier; + +public abstract class AbstractStateBotAction> extends AbstractBotAction { + + public AbstractStateBotAction(String name, Supplier creator) { + super(name, creator); + this.setDoNumber(-1); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java similarity index 89% rename from leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java rename to leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index 6cea5c42..9685e47f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -9,9 +9,9 @@ import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings; -public abstract class ServerTimerBotAction> extends ServerBotAction { +public abstract class AbstractTimerBotAction> extends AbstractBotAction { - public ServerTimerBotAction(String name, Supplier creator) { + public AbstractTimerBotAction(String name, Supplier creator) { super(name, creator); this.addArgument("delay", integer(0)) .suggests(strings("0", "5", "10", "20")) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java similarity index 95% rename from leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java rename to leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 67657ec1..1a367cfb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -12,12 +12,12 @@ import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; -public abstract class ServerUseBotAction> extends ServerTimerBotAction { +public abstract class AbstractUseBotAction> extends AbstractTimerBotAction { private int useTickTimeout = -1; private int alreadyUsedTick = 0; private int useItemRemainingTicks = 0; - public ServerUseBotAction(String name, Supplier supplier) { + public AbstractUseBotAction(String name, Supplier supplier) { super(name, supplier); this.addArgument("use_timeout", integer(-1)) .suggests((context, builder) -> { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java index c062b3e0..6a3add3b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java @@ -5,7 +5,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftAttackAction; -public class ServerAttackAction extends ServerTimerBotAction { +public class ServerAttackAction extends AbstractTimerBotAction { public ServerAttackAction() { super("attack", ServerAttackAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java index 470c62fb..36a2e621 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java @@ -13,7 +13,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftBreakBlockAction; -public class ServerBreakBlockAction extends ServerTimerBotAction { +public class ServerBreakBlockAction extends AbstractTimerBotAction { public ServerBreakBlockAction() { super("break", ServerBreakBlockAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java index a2818e7e..68e7e817 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java @@ -4,7 +4,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftDropAction; -public class ServerDropAction extends ServerTimerBotAction { +public class ServerDropAction extends AbstractTimerBotAction { public ServerDropAction() { super("drop", ServerDropAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java index 015c8777..32cc7c14 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java @@ -9,7 +9,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftFishAction; -public class ServerFishAction extends ServerTimerBotAction { +public class ServerFishAction extends AbstractTimerBotAction { public ServerFishAction() { super("fish", ServerFishAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java index 1930c1a7..f7571a79 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java @@ -4,7 +4,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftJumpAction; -public class ServerJumpAction extends ServerTimerBotAction { +public class ServerJumpAction extends AbstractTimerBotAction { public ServerJumpAction() { super("jump", ServerJumpAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index 539a0dfb..c65d2199 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -16,7 +16,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; import org.leavesmc.leaves.neo_command.CommandContext; -public class ServerLookAction extends ServerBotAction { +public class ServerLookAction extends AbstractBotAction { private static final Vector ZERO_VECTOR = new Vector(0, 0, 0); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java index 464bb761..39da096b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java @@ -11,7 +11,7 @@ import java.util.Comparator; import java.util.List; -public class ServerMountAction extends ServerBotAction { +public class ServerMountAction extends AbstractBotAction { public ServerMountAction() { super("mount", ServerMountAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 3dc723bc..6ed01137 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -15,7 +15,7 @@ import static java.util.stream.Collectors.toMap; import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings; -public class ServerMoveAction extends ServerStateBotAction { +public class ServerMoveAction extends AbstractStateBotAction { private static final Map NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap( it -> it.name, it -> it diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 03c0e8d0..7218a740 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -11,7 +11,7 @@ import java.text.DecimalFormat; -public class ServerRotationAction extends ServerBotAction { +public class ServerRotationAction extends AbstractBotAction { private static final DecimalFormat DF = new DecimalFormat("0.00"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java index 8476669a..7c6ac393 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java @@ -5,7 +5,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -public class ServerSneakAction extends ServerStateBotAction { +public class ServerSneakAction extends AbstractStateBotAction { public ServerSneakAction() { super("sneak", ServerSneakAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java deleted file mode 100644 index c87f1ffc..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.leavesmc.leaves.bot.agent.actions; - -import java.util.function.Supplier; - -public abstract class ServerStateBotAction> extends ServerBotAction { - - public ServerStateBotAction(String name, Supplier creator) { - super(name, creator); - this.setDoNumber(-1); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java index 9f6e7efc..12d737e3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java @@ -6,7 +6,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction; -public class ServerSwapAction extends ServerBotAction { +public class ServerSwapAction extends AbstractBotAction { public ServerSwapAction() { super("swap", ServerSwapAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java index fce55dc5..df5b0bf5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java @@ -5,7 +5,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction; -public class ServerSwimAction extends ServerStateBotAction { +public class ServerSwimAction extends AbstractStateBotAction { public ServerSwimAction() { super("swim", ServerSwimAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java index 0172692f..ce5884b8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java @@ -6,7 +6,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction; -public class ServerUseItemAction extends ServerUseBotAction { +public class ServerUseItemAction extends AbstractUseBotAction { public ServerUseItemAction() { super("use", ServerUseItemAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java index ce979217..bfb5f537 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java @@ -17,7 +17,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn; import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo; -public class ServerUseItemAutoAction extends ServerUseBotAction { +public class ServerUseItemAutoAction extends AbstractUseBotAction { public ServerUseItemAutoAction() { super("use_auto", ServerUseItemAutoAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java index 4983edb7..b05d8ab1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java @@ -7,7 +7,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem; -public class ServerUseItemOffhandAction extends ServerUseBotAction { +public class ServerUseItemOffhandAction extends AbstractUseBotAction { public ServerUseItemOffhandAction() { super("use_offhand", ServerUseItemOffhandAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java index bec8358f..ee23b7a6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java @@ -8,7 +8,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction; -public class ServerUseItemOnAction extends ServerUseBotAction { +public class ServerUseItemOnAction extends AbstractUseBotAction { public ServerUseItemOnAction() { super("use_on", ServerUseItemOnAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java index 09f69565..ac06e27c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java @@ -8,7 +8,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn; -public class ServerUseItemOnOffhandAction extends ServerUseBotAction { +public class ServerUseItemOnOffhandAction extends AbstractUseBotAction { public ServerUseItemOnOffhandAction() { super("use_on_offhand", ServerUseItemOnOffhandAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java index 5f294055..9d985c0c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java @@ -9,7 +9,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction; -public class ServerUseItemToAction extends ServerUseBotAction { +public class ServerUseItemToAction extends AbstractUseBotAction { public ServerUseItemToAction() { super("use_to", ServerUseItemToAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java index 733246df..6ce3aec6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java @@ -8,7 +8,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo; -public class ServerUseItemToOffhandAction extends ServerUseBotAction { +public class ServerUseItemToOffhandAction extends AbstractUseBotAction { public ServerUseItemToOffhandAction() { super("use_to_offhand", ServerUseItemToOffhandAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java new file mode 100644 index 00000000..81d05050 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -0,0 +1,102 @@ +package org.leavesmc.leaves.bot.agent.configs; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.kyori.adventure.text.Component; +import net.minecraft.nbt.CompoundTag; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.WrappedArgument; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.function.Supplier; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; + +public abstract class AbstractBotConfig> { + private final String name; + private final WrappedArgument argument; + private final Supplier creator; + + protected ServerBot bot; + + public AbstractBotConfig(String name, ArgumentType type, Supplier creator) { + this.name = name; + this.argument = new WrappedArgument<>(name, type); + if (shouldApplySuggestions()) { + this.argument.suggests(this::applySuggestions); + } + this.creator = creator; + } + + @SuppressWarnings("RedundantThrows") + public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { + } + + public AbstractBotConfig setBot(ServerBot bot) { + this.bot = bot; + return this; + } + + public E create() { + return creator.get(); + } + + public abstract O getValue(); + + public abstract void setValue(O value) throws CommandSyntaxException; + + public abstract O loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; + + public List> getExtraData() { + return List.of(); + } + + public String getName() { + return name; + } + + public Component getNameComponent() { + Component result = text(getName(), AQUA); + if (!getExtraData().isEmpty()) { + result = result.hoverEvent(showText( + getExtraData().stream() + .map(pair -> text(pair.getKey() + "=" + pair.getValue())) + .reduce((a, b) -> a.append(text(", ")).append(b)) + .orElseGet(() -> text("")) + )); + } + return result; + } + + public WrappedArgument getArgument() { + return argument; + } + + public ServerBot getBot() { + return bot; + } + + @NotNull + public CompoundTag save(@NotNull CompoundTag nbt) { + nbt.putString("configName", this.name); + return nbt; + } + + public abstract void load(@NotNull CompoundTag nbt); + + private boolean shouldApplySuggestions() { + for (Method method : getClass().getDeclaredMethods()) { + if (method.getName().equals("applySuggestions")) { + return method.getDeclaringClass() != AbstractBotConfig.class; + } + } + return false; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index 8ef871cc..b82fec5d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -1,22 +1,16 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; - -public class AlwaysSendDataConfig extends AbstractBotConfig { - - public static final String NAME = "always_send_data"; +import org.leavesmc.leaves.neo_command.CommandContext; +public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; public AlwaysSendDataConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("always_send_data", BoolArgumentType.bool(), AlwaysSendDataConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.canSendDataAlways; } @@ -30,16 +24,21 @@ public void setValue(Boolean value) { this.value = value; } + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.canSendDataAlways)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.canSendDataAlways)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java index 1b0a02f0..ee3e119a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java @@ -1,23 +1,17 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.waypoints.ServerWaypointManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; - -public class LocatorBarConfig extends AbstractBotConfig { - - public static final String NAME = "enable_locator_bar"; +import org.leavesmc.leaves.neo_command.CommandContext; +public class LocatorBarConfig extends AbstractBotConfig { private boolean value; public LocatorBarConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("enable_locator_bar", BoolArgumentType.bool(), LocatorBarConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.enableLocatorBar; } @@ -27,7 +21,7 @@ public Boolean getValue() { } @Override - public void setValue(Boolean value) throws IllegalArgumentException { + public void setValue(@NotNull Boolean value) throws IllegalArgumentException { this.value = value; ServerWaypointManager manager = this.bot.level().getWaypointManager(); if (value) { @@ -37,15 +31,20 @@ public void setValue(Boolean value) throws IllegalArgumentException { } } + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); + } + @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.enableLocatorBar)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.enableLocatorBar)); } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 56751f72..1c6b832f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -1,21 +1,27 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.nbt.CompoundTag; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.neo_command.CommandContext; -import java.util.List; +import static net.minecraft.network.chat.Component.literal; -public class SimulationDistanceConfig extends AbstractBotConfig { - - public static final String NAME = "simulation_distance"; +public class SimulationDistanceConfig extends AbstractBotConfig { public SimulationDistanceConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.INTEGER).setSuggestion(0, Pair.of(List.of("2", "10"), ""))); + super("simulation_distance", IntegerArgumentType.integer(2, 32), SimulationDistanceConfig::new); + } + + @Override + public void applySuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { + builder.suggest("2", literal("Minimum simulation distance")); + builder.suggest("8"); + builder.suggest("12"); + builder.suggest("16"); + builder.suggest("32", literal("Maximum simulation distance")); } @Override @@ -25,22 +31,24 @@ public Integer getValue() { @Override public void setValue(Integer value) { - if (value < 2 || value > 32) { - throw new IllegalArgumentException("simulation_distance must be a number between 2 and 32, got: " + value); - } this.bot.getBukkitEntity().setSimulationDistance(value); } + @Override + public Integer loadFromCommand(@NotNull CommandContext context) { + return context.getInteger(getName()); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putInt(NAME, this.getValue()); + nbt.putInt(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getIntOr(NAME, LeavesConfig.modify.fakeplayer.inGame.getSimulationDistance(this.bot))); + this.setValue(nbt.getIntOr(getName(), LeavesConfig.modify.fakeplayer.inGame.getSimulationDistance(this.bot))); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index cf4b0610..14e297fd 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -1,20 +1,15 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.neo_command.CommandContext; -import java.util.List; - -public class SkipSleepConfig extends AbstractBotConfig { - - public static final String NAME = "skip_sleep"; +public class SkipSleepConfig extends AbstractBotConfig { public SkipSleepConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("skip_sleep", BoolArgumentType.bool(), SkipSleepConfig::new); } @Override @@ -27,15 +22,20 @@ public void setValue(Boolean value) throws IllegalArgumentException { bot.fauxSleeping = value; } + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); + } + @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.canSkipSleep)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.canSkipSleep)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index 13be5fee..6b5dbdde 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -1,22 +1,19 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.neo_command.CommandContext; import java.util.List; -public class SpawnPhantomConfig extends AbstractBotConfig { - - public static final String NAME = "spawn_phantom"; - +public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; public SpawnPhantomConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("spawn_phantom", BoolArgumentType.bool(), SpawnPhantomConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.canSpawnPhantom; } @@ -31,22 +28,24 @@ public void setValue(Boolean value) throws IllegalArgumentException { } @Override - public List getMessage() { - return List.of( - bot.getScoreboardName() + "'s spawn_phantom: " + this.getValue(), - bot.getScoreboardName() + "'s not_sleeping_ticks: " + bot.notSleepTicks - ); + public List> getExtraData() { + return List.of(Pair.of("not_sleeping_ticks", String.valueOf(bot.notSleepTicks))); + } + + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); } @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.canSpawnPhantom)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.canSpawnPhantom)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index 0615a439..961f6563 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -1,27 +1,38 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; - -public class TickTypeConfig extends AbstractBotConfig { - - private static final String NAME = "tick_type"; - private static final CommandArgumentType TICK_TYPE_ARGUMENT = CommandArgumentType.ofEnum(ServerBot.TickType.class); +import org.leavesmc.leaves.neo_command.CommandContext; +public class TickTypeConfig extends AbstractBotConfig { private ServerBot.TickType value; public TickTypeConfig() { - super(NAME, CommandArgument.of(TICK_TYPE_ARGUMENT).setSuggestion(0, List.of("network", "entity_list"))); + super("tick_type", StringArgumentType.word(), TickTypeConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.tickType; } + @Override + public void applySuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { + builder.suggest("network"); + builder.suggest("entity_list"); + } + + @Override + public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException { + String raw = context.getString(getName()); + return switch (raw) { + case "network" -> ServerBot.TickType.NETWORK; + case "entity_list" -> ServerBot.TickType.ENTITY_LIST; + default -> throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + }; + } + @Override public ServerBot.TickType getValue() { return value; @@ -36,12 +47,17 @@ public void setValue(ServerBot.TickType value) throws IllegalArgumentException { @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putString(NAME, this.getValue().toString()); + nbt.putString(getName(), this.getValue().toString()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(TICK_TYPE_ARGUMENT.parse(nbt.getStringOr(NAME, LeavesConfig.modify.fakeplayer.inGame.tickType.name()))); + String raw = nbt.getStringOr(getName(), LeavesConfig.modify.fakeplayer.inGame.tickType.name()); + this.setValue(switch (raw) { + case "network" -> ServerBot.TickType.NETWORK; + case "entity_list" -> ServerBot.TickType.ENTITY_LIST; + default -> throw new IllegalStateException("Unexpected bot tick type value: " + raw); + }); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java index 883a47bf..e066fe4a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java @@ -1,110 +1,110 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.network.chat.Component; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.bot.agent.Configs; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotConfigModifyEvent; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import static net.kyori.adventure.text.Component.text; - -public class BotConfigCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 2) { - sender.sendMessage(text("Use /bot config to modify fakeplayer's config", NamedTextColor.RED)); - return; - } - - ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - if (!Configs.getConfigNames().contains(args[1])) { - sender.sendMessage(text("This config is not accept", NamedTextColor.RED)); - return; - } - - AbstractBotConfig config = bot.getConfig(Objects.requireNonNull(Configs.getConfig(args[1]))); - if (args.length < 3) { - config.getMessage().forEach(sender::sendMessage); - } else { - String[] realArgs = Arrays.copyOfRange(args, 2, args.length); - - BotConfigModifyEvent event = new BotConfigModifyEvent(bot.getBukkitEntity(), config.getName(), realArgs, sender); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - return; - } - CommandArgumentResult result = config.getArgument().parse(0, realArgs); - - try { - config.setFromCommand(result); - config.getChangeMessage().forEach(sender::sendMessage); - } catch (IllegalArgumentException e) { - sender.sendMessage(text(e.getMessage(), NamedTextColor.RED)); - } - } - } - - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - ServerBot serverBot = null; - - if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { - builder.suggest("<" + args[0] + " not found>"); - return; - } - - switch (args.length) { - case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - case 2 -> Configs.getConfigNames().forEach(builder::suggest); - case 3, 4 -> { - Configs config = Configs.getConfig(args[1]); - if (config == null) { - return; - } - AbstractBotConfig botConfig = serverBot.getConfig(config); - Pair, String> results = botConfig.getArgument().suggestion(args.length - 3, sender, args[args.length - 1]); - if (results == null || results.getLeft() == null) { - return; - } - - for (String s : results.getLeft()) { - if (results.getRight() != null) { - builder.suggest(s, Component.literal(results.getRight())); - } else { - builder.suggest(s); - } - } - } - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canModifyConfig; - } -} +//package org.leavesmc.leaves.bot.subcommands; +// +//import net.kyori.adventure.text.format.NamedTextColor; +//import net.minecraft.network.chat.Component; +//import org.apache.commons.lang3.tuple.Pair; +//import org.bukkit.Bukkit; +//import org.bukkit.Location; +//import org.bukkit.command.CommandSender; +//import org.jetbrains.annotations.NotNull; +//import org.jetbrains.annotations.Nullable; +//import org.leavesmc.leaves.LeavesConfig; +//import org.leavesmc.leaves.bot.BotList; +//import org.leavesmc.leaves.bot.ServerBot; +//import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; +//import org.leavesmc.leaves.bot.agent.Configs; +//import org.leavesmc.leaves.command.CommandArgumentResult; +//import org.leavesmc.leaves.command.LeavesSubcommand; +//import org.leavesmc.leaves.command.LeavesSuggestionBuilder; +//import org.leavesmc.leaves.event.bot.BotConfigModifyEvent; +// +//import java.util.Arrays; +//import java.util.List; +//import java.util.Objects; +// +//import static net.kyori.adventure.text.Component.text; +// +//public class BotConfigCommand implements LeavesSubcommand { +// +// @Override +// public void execute(CommandSender sender, String subCommand, String[] args) { +// if (args.length < 2) { +// sender.sendMessage(text("Use /bot config to modify fakeplayer's config", NamedTextColor.RED)); +// return; +// } +// +// ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); +// if (bot == null) { +// sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); +// return; +// } +// +// if (!Configs.getConfigNames().contains(args[1])) { +// sender.sendMessage(text("This config is not accept", NamedTextColor.RED)); +// return; +// } +// +// AbstractBotConfig config = bot.getConfig(Objects.requireNonNull(Configs.getConfig(args[1]))); +// if (args.length < 3) { +// config.getMessage().forEach(sender::sendMessage); +// } else { +// String[] realArgs = Arrays.copyOfRange(args, 2, args.length); +// +// BotConfigModifyEvent event = new BotConfigModifyEvent(bot.getBukkitEntity(), config.getName(), realArgs, sender); +// Bukkit.getPluginManager().callEvent(event); +// +// if (event.isCancelled()) { +// return; +// } +// CommandArgumentResult result = config.getArgument().parse(0, realArgs); +// +// try { +// config.setFromCommand(result); +// config.getChangeMessage().forEach(sender::sendMessage); +// } catch (IllegalArgumentException e) { +// sender.sendMessage(text(e.getMessage(), NamedTextColor.RED)); +// } +// } +// } +// +// +// @Override +// public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { +// BotList botList = BotList.INSTANCE; +// ServerBot serverBot = null; +// +// if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { +// builder.suggest("<" + args[0] + " not found>"); +// return; +// } +// +// switch (args.length) { +// case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); +// case 2 -> Configs.getConfigNames().forEach(builder::suggest); +// case 3, 4 -> { +// Configs config = Configs.getConfig(args[1]); +// if (config == null) { +// return; +// } +// AbstractBotConfig botConfig = serverBot.getConfig(config); +// Pair, String> results = botConfig.getArgument().suggestion(args.length - 3, sender, args[args.length - 1]); +// if (results == null || results.getLeft() == null) { +// return; +// } +// +// for (String s : results.getLeft()) { +// if (results.getRight() != null) { +// builder.suggest(s, Component.literal(results.getRight())); +// } else { +// builder.suggest(s); +// } +// } +// } +// } +// } +// +// @Override +// public boolean isEnabled() { +// return LeavesConfig.modify.fakeplayer.canModifyConfig; +// } +//} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java index de83f04c..e8205d26 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; import org.leavesmc.leaves.entity.bot.actions.CraftBotAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; @@ -63,7 +63,7 @@ public void stopAction(int index) { @Override public void stopAllActions() { - for (ServerBotAction action : this.getHandle().getBotActions()) { + for (AbstractBotAction action : this.getHandle().getBotActions()) { action.stop(this.getHandle(), BotActionStopEvent.Reason.PLUGIN); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java index dcbf2330..550985c4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java @@ -9,7 +9,7 @@ import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Actions; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; import org.leavesmc.leaves.event.bot.BotCreateEvent; @@ -55,7 +55,7 @@ public Collection getBots() { @SuppressWarnings("unchecked") @Override public > T newAction(@NotNull Class type) { - ServerBotAction action = Actions.getForClass(type); + AbstractBotAction action = Actions.getForClass(type); if (action == null) { throw new IllegalArgumentException("No action registered for type: " + type.getName()); } else { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java index f3fbd60e..b0c0c20c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java @@ -2,14 +2,14 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; -public abstract class CraftBotAction, S extends ServerBotAction> implements BotAction { +public abstract class CraftBotAction, S extends AbstractBotAction> implements BotAction { protected final S serverAction; protected final Function creator; @@ -23,7 +23,7 @@ public CraftBotAction(S serverAction, Function creator) { this.creator = creator; } - public ServerBotAction getHandle() { + public AbstractBotAction getHandle() { return serverAction; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java index 532c3e37..2ff20416 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java @@ -1,11 +1,11 @@ package org.leavesmc.leaves.entity.bot.actions; -import org.leavesmc.leaves.bot.agent.actions.ServerTimerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractTimerBotAction; import org.leavesmc.leaves.entity.bot.action.TimerBotAction; import java.util.function.Function; -public class CraftTimerBotAction, S extends ServerTimerBotAction> extends CraftBotAction implements TimerBotAction { +public class CraftTimerBotAction, S extends AbstractTimerBotAction> extends CraftBotAction implements TimerBotAction { public CraftTimerBotAction(S serverAction, Function creator) { super(serverAction, creator); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java index 1ff2c7f4..d075ccc7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java @@ -46,6 +46,18 @@ public CommandSender getSender() { return source.getArgument(name, clazz); } + public int getInteger(final String name) { + return source.getArgument(name, Integer.class); + } + + public boolean getBoolean(final String name) { + return source.getArgument(name, Boolean.class); + } + + public String getString(final String name) { + return source.getArgument(name, String.class); + } + @SuppressWarnings("unchecked") public @NotNull V getArgument(final Class> nodeClass) { String name = getNameForNode(nodeClass); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java index 32bc4a94..268efef0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java @@ -16,7 +16,7 @@ public class ActionCommand extends BotSubcommand { public ActionCommand() { super("action"); - children(ActionCommand.BotArgument::new); + children(BotArgument::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java index 051bb3b1..477cd14c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java @@ -1,10 +1,106 @@ package org.leavesmc.leaves.neo_command.bot.subcommands; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.commands.CommandSourceStack; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.Configs; +import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; +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.BotSubcommand; +import java.util.function.Supplier; + +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; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + public class ConfigCommand extends BotSubcommand { public ConfigCommand() { super("config"); + children(BotArgument::new); + } + + private static class BotArgument extends CustomArgumentNode { + + protected BotArgument() { + super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + Configs.getConfigs().stream() + .map(this::configNodeCreator) + .forEach(this::children); + } + + @Contract(pure = true) + private @NotNull Supplier configNodeCreator(AbstractBotConfig config) { + return () -> new ConfigNode<>(config); + } + + public static @NotNull ServerBot getBot(@NotNull CommandContext context) throws CommandSyntaxException { + return context.getCustomArgument(BotArgument.class); + } + } + + private static class ConfigNode extends LiteralNode { + private final AbstractBotConfig config; + + private ConfigNode(@NotNull AbstractBotConfig config) { + super(config.getName()); + this.config = config; + } + + @Override + protected ArgumentBuilder compileBase() { + RequiredArgumentBuilder argument = config.getArgument() + .compile() + .executes(mojangCtx -> { + CommandContext ctx = new CommandContext(mojangCtx); + return executeSet(ctx) ? 1 : 0; + }); + return super.compileBase() + .then(argument); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + ServerBot bot = BotArgument.getBot(context); + AbstractBotConfig botConfig = bot.getConfig(config); + context.getSender().sendMessage(join(spaces(), + text("Bot", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("config", GRAY), + botConfig.getNameComponent(), + text("is", GRAY), + text(String.valueOf(bot.getConfig(config).getValue()), AQUA) + )); + return true; + } + + private boolean executeSet(CommandContext context) throws CommandSyntaxException { + ServerBot bot = BotArgument.getBot(context); + AbstractBotConfig botConfig = bot.getConfig(config); + try { + botConfig.setValue(botConfig.loadFromCommand(context)); + } catch (ClassCastException e) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + context.getSender().sendMessage(join(spaces(), + text("Bot", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("config", GRAY), + botConfig.getNameComponent(), + text("changed to", GRAY), + text(String.valueOf(botConfig.getValue()), AQUA) + )); + return true; + } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java index 754309e0..54f90df9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java @@ -4,7 +4,7 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.neo_command.CommandContext; import org.leavesmc.leaves.neo_command.LiteralNode; import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand; @@ -30,7 +30,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE ServerBot bot = ActionCommand.BotArgument.getBot(context); CommandSender sender = context.getSender(); - List> actions = bot.getBotActions(); + List> actions = bot.getBotActions(); if (actions.isEmpty()) { sender.sendMessage(text("This bot has no active actions", GRAY)); return true; @@ -41,7 +41,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE .append(text("'s action list:", GRAY)) ); for (int i = 0; i < actions.size(); i++) { - ServerBotAction action = actions.get(i); + AbstractBotAction action = actions.get(i); sender.sendMessage(join(spaces(), text(i, GRAY), text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java index ea1a76ce..7611e284 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Actions; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.neo_command.CommandContext; import org.leavesmc.leaves.neo_command.LiteralNode; import org.leavesmc.leaves.neo_command.WrappedArgument; @@ -38,7 +38,7 @@ public StartCommand() { .forEach(this::children); } - private boolean handleStartCommand(CommandContext context, @NotNull ServerBotAction action) throws CommandSyntaxException { + private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotAction action) throws CommandSyntaxException { ServerBot bot = getBot(context); CommandSender sender = context.getSender(); @@ -56,51 +56,60 @@ private boolean handleStartCommand(CommandContext context, @NotNull ServerBotAct } @Contract(pure = true) - private @NotNull Supplier actionNodeCreator(ServerBotAction action) { - return () -> new LiteralNode(action.getName()) { - @Override - protected ArgumentBuilder compile() { - ArgumentBuilder builder = super.compile(); - - Map>>> arguments = action.getArguments(); - Command executor = context -> { - if (handleStartCommand(new CommandContext(context), action)) { - return Command.SINGLE_SUCCESS; - } else { - return 0; - } - }; - for (Map.Entry>>> entry : arguments.entrySet()) { - List>> value = entry.getValue(); - ArgumentBuilder branchArgumentBuilder = null; - - for (Pair> stringWrappedArgumentPair : value.reversed()) { - WrappedArgument argument = stringWrappedArgumentPair.getRight(); - if (branchArgumentBuilder == null) { - branchArgumentBuilder = argument.compile().executes(executor); - } else { - branchArgumentBuilder = argument.compile().then(branchArgumentBuilder); - if (argument.isOptional()) { - branchArgumentBuilder = branchArgumentBuilder.executes(executor); - } - } - } + private @NotNull Supplier actionNodeCreator(AbstractBotAction action) { + return () -> new ActionLiteralNode(action); + } - if (value.getFirst().getRight().isOptional() || value.isEmpty()) { - builder = builder.executes(executor); - } + private class ActionLiteralNode extends LiteralNode { + private final AbstractBotAction action; + + public ActionLiteralNode(@NotNull AbstractBotAction action) { + super(action.getName()); + this.action = action; + } + + @Override + protected ArgumentBuilder compile() { + ArgumentBuilder builder = super.compile(); - if (branchArgumentBuilder != null) { - builder = builder.then(branchArgumentBuilder); + Map>>> arguments = action.getArguments(); + Command executor = context -> { + if (handleStartCommand(new CommandContext(context), action)) { + return Command.SINGLE_SUCCESS; + } else { + return 0; + } + }; + for (Map.Entry>>> entry : arguments.entrySet()) { + List>> value = entry.getValue(); + ArgumentBuilder branchArgumentBuilder = null; + + for (Pair> stringWrappedArgumentPair : value.reversed()) { + WrappedArgument argument = stringWrappedArgumentPair.getRight(); + if (branchArgumentBuilder == null) { + branchArgumentBuilder = argument.compile().executes(executor); + } else { + branchArgumentBuilder = argument.compile().then(branchArgumentBuilder); + if (argument.isOptional()) { + branchArgumentBuilder = branchArgumentBuilder.executes(executor); + } } } - if (arguments.isEmpty()) { + if (value.getFirst().getRight().isOptional() || value.isEmpty()) { builder = builder.executes(executor); } - return builder; + if (branchArgumentBuilder != null) { + builder = builder.then(branchArgumentBuilder); + } } - }; + + if (arguments.isEmpty()) { + builder = builder.executes(executor); + } + + return builder; + } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java index e23a077f..d7b7eda1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java @@ -8,7 +8,7 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; import org.leavesmc.leaves.neo_command.ArgumentNode; import org.leavesmc.leaves.neo_command.CommandContext; @@ -46,7 +46,7 @@ protected CompletableFuture getSuggestions(CommandContext context, ServerBot bot = ActionCommand.BotArgument.getBot(context); for (int i = 0; i < bot.getBotActions().size(); i++) { - ServerBotAction action = bot.getBotActions().get(i); + AbstractBotAction action = bot.getBotActions().get(i); builder.suggest(String.valueOf(i), Component.literal(action.getName())); } @@ -67,7 +67,7 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.integerTooHigh().create(index, maxIndex); } - ServerBotAction action = bot.getBotActions().get(index); + AbstractBotAction action = bot.getBotActions().get(index); BotActionStopEvent event = new BotActionStopEvent( bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender ); @@ -98,16 +98,16 @@ public StopAll() { protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { ServerBot bot = ActionCommand.BotArgument.getBot(context); - List> actions = bot.getBotActions(); + List> actions = bot.getBotActions(); CommandSender sender = context.getSender(); if (actions.isEmpty()) { sender.sendMessage(text("This bot has no active actions", GRAY)); return true; } - Set> canceled = new HashSet<>(); - Set> forRemoval = new HashSet<>(); - for (ServerBotAction action : actions) { + Set> canceled = new HashSet<>(); + Set> forRemoval = new HashSet<>(); + for (AbstractBotAction action : actions) { BotActionStopEvent event = new BotActionStopEvent( bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender ); @@ -132,7 +132,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), text("'s action list, but following actions' stop was canceled by plugin:", GRAY) )); - for (ServerBotAction action : canceled) { + for (AbstractBotAction action : canceled) { context.getSender().sendMessage( text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) ); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java index ad547038..6e203d93 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java @@ -48,9 +48,9 @@ protected CompletableFuture getSuggestions(@NotNull CommandContext int dotIndex = path.lastIndexOf("."); builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2); getListClosestMatchingLast( - path.substring(dotIndex + 1), - GlobalConfigManager.getVerifiedConfigSubPaths(path) - ).forEach(builder::suggest); + path.substring(dotIndex + 1), + GlobalConfigManager.getVerifiedConfigSubPaths(path) + ).forEach(builder::suggest); return builder.buildFuture(); } From ce40c8eef686ac5873c4f8bcdd2a4a9e7a3e3e7a Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 10:16:53 +0800 Subject: [PATCH 06/29] feat: switch to new bot command --- .../org/leavesmc/leaves/LeavesConfig.java | 33 ++-- .../org/leavesmc/leaves/bot/BotCommand.java | 44 ----- .../bot/subcommands/BotActionCommand.java | 181 ------------------ .../bot/subcommands/BotConfigCommand.java | 110 ----------- .../bot/subcommands/BotCreateCommand.java | 100 ---------- .../bot/subcommands/BotListCommand.java | 77 -------- .../bot/subcommands/BotLoadCommand.java | 48 ----- .../bot/subcommands/BotRemoveCommand.java | 117 ----------- .../bot/subcommands/BotSaveCommand.java | 51 ----- .../leaves/neo_command/bot/BotCommand.java | 2 +- .../bot/subcommands/ConfigCommand.java | 6 + 11 files changed, 22 insertions(+), 747 deletions(-) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 289fbdd1..bd4f26a1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -14,7 +14,6 @@ import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.bot.BotCommand; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.command.LeavesCommand; @@ -31,6 +30,7 @@ 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.bot.BotCommand; import org.leavesmc.leaves.profile.LeavesMinecraftSessionService; import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule; import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules; @@ -58,6 +58,7 @@ import java.util.Random; import java.util.function.Predicate; +@SuppressWarnings({"unused", "FieldMayBeFinal", "FieldCanBeLocal"}) public final class LeavesConfig { public static final String CONFIG_HEADER = "Configuration file for Leaves."; @@ -151,16 +152,15 @@ private static class FakeplayerValidator extends BooleanConfigValidator { @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { if (value) { - registerCommand("bot", new BotCommand()); - org.leavesmc.leaves.neo_command.bot.BotCommand.INSTANCE.register(); + BotCommand.INSTANCE.register(); Actions.registerAll(); } else { unregisterCommand("bot"); - org.leavesmc.leaves.neo_command.bot.BotCommand.INSTANCE.unregister(); + BotCommand.INSTANCE.unregister(); } if (old != null && !old.equals(value)) { Bukkit.getOnlinePlayers().stream() - .filter(org.leavesmc.leaves.neo_command.bot.BotCommand::hasPermission) + .filter(BotCommand::hasPermission) .forEach(org.bukkit.entity.Player::updateCommands); } } @@ -206,10 +206,9 @@ 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); + BotCommand.hasPermission(sender) + || BotCommand.hasPermission(sender, "action") + ).forEach(org.bukkit.entity.Player::updateCommands); } } } @@ -223,10 +222,9 @@ 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); + BotCommand.hasPermission(sender) + || BotCommand.hasPermission(sender, "config") + ).forEach(org.bukkit.entity.Player::updateCommands); } } } @@ -240,11 +238,10 @@ 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); + BotCommand.hasPermission(sender) + || BotCommand.hasPermission(sender, "save") + || BotCommand.hasPermission(sender, "load") + ).forEach(org.bukkit.entity.Player::updateCommands); } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java deleted file mode 100644 index 32b5482d..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.leavesmc.leaves.bot; - -import net.minecraft.Util; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.subcommands.BotCreateCommand; -import org.leavesmc.leaves.bot.subcommands.BotListCommand; -import org.leavesmc.leaves.bot.subcommands.BotLoadCommand; -import org.leavesmc.leaves.bot.subcommands.BotRemoveCommand; -import org.leavesmc.leaves.bot.subcommands.BotSaveCommand; -import org.leavesmc.leaves.command.LeavesRootCommand; -import org.leavesmc.leaves.command.LeavesSubcommand; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public class BotCommand extends LeavesRootCommand { - - // subcommand label -> subcommand - private static final Map SUBCOMMANDS = Util.make(() -> { - final Map, LeavesSubcommand> commands = new HashMap<>(); - commands.put(Set.of("create"), new BotCreateCommand()); - commands.put(Set.of("remove"), new BotRemoveCommand()); -// commands.put(Set.of("action"), new BotActionCommand()); -// commands.put(Set.of("config"), new BotConfigCommand()); - commands.put(Set.of("save"), new BotSaveCommand()); - commands.put(Set.of("load"), new BotLoadCommand()); - commands.put(Set.of("list"), new BotListCommand()); - - 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)); - }); - - public BotCommand() { - super("bot", "FakePlayer Command", "bukkit.command.bot", SUBCOMMANDS); - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.enable; - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java deleted file mode 100644 index c8c933ec..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java +++ /dev/null @@ -1,181 +0,0 @@ -//package org.leavesmc.leaves.bot.subcommands; -// -//import net.kyori.adventure.text.format.NamedTextColor; -//import net.minecraft.network.chat.Component; -//import org.apache.commons.lang3.tuple.Pair; -//import org.bukkit.Location; -//import org.bukkit.command.CommandSender; -//import org.bukkit.craftbukkit.entity.CraftPlayer; -//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.bot.agent.Actions; -//import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; -//import org.leavesmc.leaves.command.LeavesSubcommand; -//import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -//import org.leavesmc.leaves.event.bot.BotActionStopEvent; -// -//import java.util.Arrays; -//import java.util.HashSet; -//import java.util.List; -//import java.util.Set; -// -//import static net.kyori.adventure.text.Component.text; -// -//public class BotActionCommand implements LeavesSubcommand { -// -// @Override -// public void execute(CommandSender sender, String subCommand, String[] args) { -// if (args.length < 2) { -// sender.sendMessage(text("Use /bot action to make fakeplayer do action", NamedTextColor.RED)); -// return; -// } -// -// ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); -// if (bot == null) { -// sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); -// return; -// } -// -// switch (args[1].toLowerCase()) { -// case "list" -> { -// sender.sendMessage(bot.getScoreboardName() + "'s action list:"); -// for (int i = 0; i < bot.getBotActions().size(); i++) { -// sender.sendMessage(i + " " + bot.getBotActions().get(i).getName()); -// } -// } -// case "start" -> executeStart(bot, sender, args); -// case "stop" -> executeStop(bot, sender, args); -// } -// } -// -// private void executeStart(ServerBot bot, CommandSender sender, String[] args) { -// if (args.length < 3) { -// sender.sendMessage(text("Invalid action", NamedTextColor.RED)); -// return; -// } -// ServerBotAction action = Actions.getForName(args[2]); -// if (action == null) { -// sender.sendMessage(text("Invalid action", NamedTextColor.RED)); -// return; -// } -// -// CraftPlayer player; -// if (sender instanceof CraftPlayer) { -// player = (CraftPlayer) sender; -// } else { -// player = bot.getBukkitEntity(); -// } -// -// String[] realArgs = Arrays.copyOfRange(args, 3, args.length); -// ServerBotAction newAction; -// try { -// newAction = action.create(); -// newAction.loadCommand(player.getHandle(), action.getArgument().parse(0, realArgs)); -// } catch (IllegalArgumentException e) { -// sender.sendMessage(text("Action create error, please check your arguments, " + e.getMessage(), NamedTextColor.RED)); -// return; -// } -// -// if (bot.addBotAction(newAction, sender)) { -// sender.sendMessage("Action " + action.getName() + " has been issued to " + bot.getName().getString()); -// } -// } -// -// private void executeStop(ServerBot bot, CommandSender sender, String[] args) { -// if (args.length < 3) { -// sender.sendMessage(text("Invalid index", NamedTextColor.RED)); -// return; -// } -// -// String index = args[2]; -// if (index.equals("all")) { -// Set> forRemoval = new HashSet<>(); -// for (int i = 0; i < bot.getBotActions().size(); i++) { -// ServerBotAction action = bot.getBotActions().get(i); -// BotActionStopEvent event = new BotActionStopEvent( -// bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender -// ); -// event.callEvent(); -// if (!event.isCancelled()) { -// forRemoval.add(action); -// action.stop(bot, BotActionStopEvent.Reason.COMMAND); -// } -// } -// bot.getBotActions().removeAll(forRemoval); -// sender.sendMessage(bot.getScoreboardName() + "'s action list cleared."); -// return; -// } -// try { -// int i = Integer.parseInt(index); -// if (i < 0 || i >= bot.getBotActions().size()) { -// sender.sendMessage(text("Invalid index", NamedTextColor.RED)); -// return; -// } -// -// ServerBotAction action = bot.getBotActions().get(i); -// BotActionStopEvent event = new BotActionStopEvent( -// bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender -// ); -// event.callEvent(); -// if (!event.isCancelled()) { -// action.stop(bot, BotActionStopEvent.Reason.COMMAND); -// bot.getBotActions().remove(i); -// sender.sendMessage(bot.getScoreboardName() + "'s " + action.getName() + " stopped."); -// -// } -// } catch (NumberFormatException e) { -// sender.sendMessage(text("Invalid index", NamedTextColor.RED)); -// } -// } -// -// @Override -// public void suggest(@NotNull CommandSender sender, @NotNull String subCommand, String @NotNull [] args, Location location, @NotNull LeavesSuggestionBuilder builder) { -// BotList botList = BotList.INSTANCE; -// ServerBot serverBot = null; -// -// if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { -// builder.suggest("<" + args[0] + " not found>"); -// return; -// } -// -// switch (args.length) { -// case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); -// case 2 -> builder.suggest("start").suggest("stop").suggest("list"); -// case 3 -> { -// switch (args[1].toLowerCase()) { -// case "start" -> Actions.getNames().forEach(builder::suggest); -// case "stop" -> { -// builder.suggest("all"); -// int[] index = new int[]{0}; -// serverBot.getBotActions().forEach(a -> builder.suggest(String.valueOf(index[0]++))); -// } -// } -// } -// case 4, 5, 6, 7 -> { -// ServerBotAction action = Actions.getForName(args[2]); -// if (action == null) { -// return; -// } -// Pair, String> results = action.getArgument().suggestion(args.length - 4, sender, args[args.length - 2]); -// if (results == null || results.getLeft() == null) { -// return; -// } -// -// for (String s : results.getLeft()) { -// if (results.getRight() != null) { -// builder.suggest(s, Component.literal(results.getRight())); -// } else { -// builder.suggest(s); -// } -// } -// } -// } -// } -// -// @Override -// public boolean isEnabled() { -// return LeavesConfig.modify.fakeplayer.canUseAction; -// } -//} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java deleted file mode 100644 index e066fe4a..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java +++ /dev/null @@ -1,110 +0,0 @@ -//package org.leavesmc.leaves.bot.subcommands; -// -//import net.kyori.adventure.text.format.NamedTextColor; -//import net.minecraft.network.chat.Component; -//import org.apache.commons.lang3.tuple.Pair; -//import org.bukkit.Bukkit; -//import org.bukkit.Location; -//import org.bukkit.command.CommandSender; -//import org.jetbrains.annotations.NotNull; -//import org.jetbrains.annotations.Nullable; -//import org.leavesmc.leaves.LeavesConfig; -//import org.leavesmc.leaves.bot.BotList; -//import org.leavesmc.leaves.bot.ServerBot; -//import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; -//import org.leavesmc.leaves.bot.agent.Configs; -//import org.leavesmc.leaves.command.CommandArgumentResult; -//import org.leavesmc.leaves.command.LeavesSubcommand; -//import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -//import org.leavesmc.leaves.event.bot.BotConfigModifyEvent; -// -//import java.util.Arrays; -//import java.util.List; -//import java.util.Objects; -// -//import static net.kyori.adventure.text.Component.text; -// -//public class BotConfigCommand implements LeavesSubcommand { -// -// @Override -// public void execute(CommandSender sender, String subCommand, String[] args) { -// if (args.length < 2) { -// sender.sendMessage(text("Use /bot config to modify fakeplayer's config", NamedTextColor.RED)); -// return; -// } -// -// ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); -// if (bot == null) { -// sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); -// return; -// } -// -// if (!Configs.getConfigNames().contains(args[1])) { -// sender.sendMessage(text("This config is not accept", NamedTextColor.RED)); -// return; -// } -// -// AbstractBotConfig config = bot.getConfig(Objects.requireNonNull(Configs.getConfig(args[1]))); -// if (args.length < 3) { -// config.getMessage().forEach(sender::sendMessage); -// } else { -// String[] realArgs = Arrays.copyOfRange(args, 2, args.length); -// -// BotConfigModifyEvent event = new BotConfigModifyEvent(bot.getBukkitEntity(), config.getName(), realArgs, sender); -// Bukkit.getPluginManager().callEvent(event); -// -// if (event.isCancelled()) { -// return; -// } -// CommandArgumentResult result = config.getArgument().parse(0, realArgs); -// -// try { -// config.setFromCommand(result); -// config.getChangeMessage().forEach(sender::sendMessage); -// } catch (IllegalArgumentException e) { -// sender.sendMessage(text(e.getMessage(), NamedTextColor.RED)); -// } -// } -// } -// -// -// @Override -// public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { -// BotList botList = BotList.INSTANCE; -// ServerBot serverBot = null; -// -// if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { -// builder.suggest("<" + args[0] + " not found>"); -// return; -// } -// -// switch (args.length) { -// case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); -// case 2 -> Configs.getConfigNames().forEach(builder::suggest); -// case 3, 4 -> { -// Configs config = Configs.getConfig(args[1]); -// if (config == null) { -// return; -// } -// AbstractBotConfig botConfig = serverBot.getConfig(config); -// Pair, String> results = botConfig.getArgument().suggestion(args.length - 3, sender, args[args.length - 1]); -// if (results == null || results.getLeft() == null) { -// return; -// } -// -// for (String s : results.getLeft()) { -// if (results.getRight() != null) { -// builder.suggest(s, Component.literal(results.getRight())); -// } else { -// builder.suggest(s); -// } -// } -// } -// } -// } -// -// @Override -// public boolean isEnabled() { -// return LeavesConfig.modify.fakeplayer.canModifyConfig; -// } -//} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java deleted file mode 100644 index 0cbd1869..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.bot.BotCreateState; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.BotUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotCreateEvent; - -import static net.kyori.adventure.text.Component.text; - -public class BotCreateCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Use /bot create [skin_name] to create a fakeplayer", NamedTextColor.RED)); - return; - } - - String botName = args[0]; - String fullName = BotUtil.getFullName(botName); - if (this.canCreate(sender, fullName)) { - BotCreateState.Builder builder = BotCreateState.builder(botName, Bukkit.getWorlds().getFirst().getSpawnLocation()).createReason(BotCreateEvent.CreateReason.COMMAND).creator(sender); - - if (args.length >= 2) { - builder.skinName(args[1]); - } - - if (sender instanceof Player player) { - builder.location(player.getLocation()); - } else if (sender instanceof ConsoleCommandSender) { - if (args.length >= 6) { - try { - World world = Bukkit.getWorld(args[2]); - double x = Double.parseDouble(args[3]); - double y = Double.parseDouble(args[4]); - double z = Double.parseDouble(args[5]); - if (world != null) { - builder.location(new Location(world, x, y, z)); - } - } catch (Exception e) { - LeavesLogger.LOGGER.warning("Can't build location", e); - } - } - } - - builder.spawnWithSkin(null); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (args.length <= 1) { - builder.suggest(""); - } - if (args.length == 2) { - builder.suggest("[SkinName]"); - } - if (sender instanceof ConsoleCommandSender && args.length == 3) { - Bukkit.getWorlds().forEach(world -> builder.suggest(world.getName())); - } - } - - private boolean canCreate(CommandSender sender, @NotNull String name) { - BotList botList = BotList.INSTANCE; - if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { - sender.sendMessage(text("This name is illegal", NamedTextColor.RED)); - return false; - } - - if (Bukkit.getPlayerExact(name) != null || botList.getBotByName(name) != null) { - sender.sendMessage(text("This player is in server", NamedTextColor.RED)); - return false; - } - - if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { - sender.sendMessage(text("This name is not allowed", NamedTextColor.RED)); - return false; - } - - if (botList.bots.size() >= LeavesConfig.modify.fakeplayer.limit) { - sender.sendMessage(text("Fakeplayer limit is full", NamedTextColor.RED)); - return false; - } - - return true; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java deleted file mode 100644 index 40088a0f..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.entity.bot.Bot; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static net.kyori.adventure.text.Component.text; - -public class BotListCommand implements LeavesSubcommand { - - @NotNull - private static String formatPlayerNameList(@NotNull List list) { - if (list.isEmpty()) { - return ""; - } - String string = list.toString(); - return string.substring(1, string.length() - 1); - } - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - BotList botList = BotList.INSTANCE; - if (args.length < 2) { - Map> botMap = new HashMap<>(); - for (World world : Bukkit.getWorlds()) { - botMap.put(world, new ArrayList<>()); - } - - for (ServerBot bot : botList.bots) { - Bot bukkitBot = bot.getBukkitEntity(); - botMap.get(bukkitBot.getWorld()).add(bukkitBot.getName()); - } - - sender.sendMessage("Total number: (" + botList.bots.size() + "/" + LeavesConfig.modify.fakeplayer.limit + ")"); - for (World world : botMap.keySet()) { - sender.sendMessage(world.getName() + "(" + botMap.get(world).size() + "): " + formatPlayerNameList(botMap.get(world))); - } - } else { - World world = Bukkit.getWorld(args[1]); - - if (world == null) { - sender.sendMessage(text("Unknown world", NamedTextColor.RED)); - return; - } - - List snowBotList = new ArrayList<>(); - for (ServerBot bot : botList.bots) { - Bot bukkitBot = bot.getBukkitEntity(); - if (bukkitBot.getWorld() == world) { - snowBotList.add(bukkitBot.getName()); - } - } - - sender.sendMessage(world.getName() + "(" + botList.bots.size() + "): " + formatPlayerNameList(snowBotList)); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - Bukkit.getWorlds().forEach(world -> builder.suggest(world.getName())); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java deleted file mode 100644 index fbd223e3..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; - -import static net.kyori.adventure.text.Component.text; - -public class BotLoadCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Use /bot load to save a fakeplayer", NamedTextColor.RED)); - return; - } - - String realName = args[0]; - BotList botList = BotList.INSTANCE; - if (!botList.getSavedBotList().contains(realName)) { - sender.sendMessage(text("This fakeplayer is not saved", NamedTextColor.RED)); - return; - } - - if (botList.loadNewBot(realName) == null) { - sender.sendMessage(text("Can't load bot, please check", NamedTextColor.RED)); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - if (args.length <= 1) { - botList.getSavedBotList().keySet().forEach(builder::suggest); - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java deleted file mode 100644 index c40bd6a7..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotRemoveEvent; -import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; - -import static net.kyori.adventure.text.Component.text; - -public class BotRemoveCommand implements LeavesSubcommand { - - private final Component errorMessage = text("Usage: /bot remove [hour] [minute] [second]", NamedTextColor.RED); - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1 || args.length > 4) { - sender.sendMessage(errorMessage); - return; - } - - BotList botList = BotList.INSTANCE; - ServerBot bot = botList.getBotByName(args[0]); - - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - if (args.length == 2 && args[1].equals("cancel")) { - if (bot.removeTaskId == -1) { - sender.sendMessage(text("This fakeplayer is not scheduled to be removed", NamedTextColor.RED)); - return; - } - Bukkit.getScheduler().cancelTask(bot.removeTaskId); - bot.removeTaskId = -1; - sender.sendMessage(text("Remove cancel")); - return; - } - - if (args.length > 1) { - long time = 0; - int h; // Preventing out-of-range - long s = 0; - long m = 0; - - try { - h = Integer.parseInt(args[1]); - if (h < 0) { - throw new NumberFormatException(); - } - time += ((long) h) * 3600 * 20; - if (args.length > 2) { - m = Long.parseLong(args[2]); - if (m > 59 || m < 0) { - throw new NumberFormatException(); - } - time += m * 60 * 20; - } - if (args.length > 3) { - s = Long.parseLong(args[3]); - if (s > 59 || s < 0) { - throw new NumberFormatException(); - } - time += s * 20; - } - } catch (NumberFormatException e) { - sender.sendMessage(errorMessage); - return; - } - - boolean isReschedule = bot.removeTaskId != -1; - - if (isReschedule) { - Bukkit.getScheduler().cancelTask(bot.removeTaskId); - } - bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> { - bot.removeTaskId = -1; - botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false); - }, time).getTaskId(); - - sender.sendMessage("This fakeplayer will be removed in " + h + "h " + m + "m " + s + "s" + (isReschedule ? " (rescheduled)" : "")); - return; - } - - botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false); - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - - if (args.length <= 1) { - botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - } - - if (args.length == 2) { - builder.suggest("cancel"); - builder.suggest("[hour]"); - } - - if (args.length > 2 && !args[1].equals("cancel")) { - switch (args.length) { - case 3 -> builder.suggest("[minute]"); - case 4 -> builder.suggest("[second]"); - } - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java deleted file mode 100644 index d1b22d9c..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotRemoveEvent; - -import static net.kyori.adventure.text.Component.text; - -public class BotSaveCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Use /bot save to save a fakeplayer", NamedTextColor.RED)); - return; - } - - BotList botList = BotList.INSTANCE; - ServerBot bot = botList.getBotByName(args[0]); - - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - if (botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true)) { - sender.sendMessage(bot.getScoreboardName() + " saved to " + bot.createState.realName()); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - if (args.length <= 1) { - botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java index ef72ef89..89947169 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java @@ -22,7 +22,7 @@ public class BotCommand extends LiteralNode { private static final String PERM_BASE = "bukkit.command.bot"; private BotCommand() { - super("bot_neo"); + super("bot"); this.children( ActionCommand::new, ListCommand::new, diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java index 477cd14c..f5aad795 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java @@ -6,6 +6,7 @@ import net.minecraft.commands.CommandSourceStack; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Configs; import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; @@ -30,6 +31,11 @@ public ConfigCommand() { children(BotArgument::new); } + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.fakeplayer.canModifyConfig && super.requires(source); + } + private static class BotArgument extends CustomArgumentNode { protected BotArgument() { From 58500b95687b235ad9cc493695c61ceeed9e0d53 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 10:19:37 +0800 Subject: [PATCH 07/29] fix: fix suppress annotation --- .../src/main/java/org/leavesmc/leaves/LeavesConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index bd4f26a1..c613b9e3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -58,7 +58,7 @@ import java.util.Random; import java.util.function.Predicate; -@SuppressWarnings({"unused", "FieldMayBeFinal", "FieldCanBeLocal"}) +@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"}) public final class LeavesConfig { public static final String CONFIG_HEADER = "Configuration file for Leaves."; @@ -332,6 +332,7 @@ public static class BlockUpdaterConfig { @GlobalConfig("armor-stand-cant-kill-by-mob-projectile") public boolean armorStandCantKillByMobProjectile = false; + @SuppressWarnings("unused") @GlobalConfig(value = "villager-infinite-discounts", validator = VillagerInfiniteDiscountsValidator.class) private boolean villagerInfiniteDiscounts = false; @@ -771,6 +772,7 @@ public void verify(RenewableCoralType old, RenewableCoralType value) throws Ille @GlobalConfig("disable-vault-blacklist") public boolean disableVaultBlacklist = false; + @SuppressWarnings("unused") @GlobalConfig(value = "exp-orb-absorb-mode", validator = ExpOrbModeValidator.class) private ExpOrbAbsorbMode expOrbAbsorbMode = ExpOrbAbsorbMode.VANILLA; @@ -1144,6 +1146,7 @@ public void verify(Boolean old, Boolean value) throws IllegalArgumentException { @GlobalConfig("login-protect") public boolean loginProtect = false; + @SuppressWarnings("unused") @GlobalConfig(value = "urls", lock = true, validator = ExtraYggdrasilUrlsValidator.class) private List serviceList = List.of("https://url.with.authlib-injector-yggdrasil"); From 3e2b63c99dad5e61402fc5e0650a8285d8566190 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 12:09:21 +0800 Subject: [PATCH 08/29] feat: add bot remove, fix stupid me --- .../org/leavesmc/leaves/LeavesConfig.java | 11 +- .../java/org/leavesmc/leaves/bot/BotList.java | 2 +- .../leavesmc/leaves/entity/bot/CraftBot.java | 3 +- .../leaves/neo_command/bot/BotCommand.java | 8 +- .../bot/subcommands/RemoveCommand.java | 155 ++++++++++++++++++ .../bot/subcommands/SaveCommand.java | 21 +-- 6 files changed, 174 insertions(+), 26 deletions(-) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index c613b9e3..3bb30b2e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -54,7 +54,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.Random; import java.util.function.Predicate; @@ -127,13 +126,6 @@ public static void registerCommand(String name, Command command) { MinecraftServer.getServer().server.syncCommands(); } - public static void unregisterCommand(String name) { - name = name.toLowerCase(Locale.ENGLISH).trim(); - MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove(name); - MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove("leaves:" + name); - MinecraftServer.getServer().server.syncCommands(); - } - public static ModifyConfig modify = new ModifyConfig(); @GlobalConfigCategory("modify") @@ -152,10 +144,9 @@ private static class FakeplayerValidator extends BooleanConfigValidator { @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { if (value) { - BotCommand.INSTANCE.register(); Actions.registerAll(); + BotCommand.INSTANCE.register(); } else { - unregisterCommand("bot"); BotCommand.INSTANCE.unregister(); } if (old != null && !old.equals(value)) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java index 9a7ba737..f0581ef1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java @@ -191,7 +191,7 @@ public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveR this.server.server.getPluginManager().callEvent(event); if (event.isCancelled() && event.getReason() != BotRemoveEvent.RemoveReason.INTERNAL) { - return true; + return false; } if (bot.removeTaskId != -1) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java index e8205d26..3ce7adac 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java @@ -70,8 +70,7 @@ public void stopAllActions() { @Override public boolean remove(boolean save) { - BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save); - return true; + return BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java index 89947169..ce526286 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java @@ -12,6 +12,7 @@ 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.RemoveCommand; import org.leavesmc.leaves.neo_command.bot.subcommands.SaveCommand; import java.util.ArrayList; @@ -24,12 +25,13 @@ public class BotCommand extends LiteralNode { private BotCommand() { super("bot"); this.children( - ActionCommand::new, ListCommand::new, - CreateCommand::new, + ConfigCommand::new, + RemoveCommand::new, LoadCommand::new, SaveCommand::new, - ConfigCommand::new + ActionCommand::new, + CreateCommand::new ); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java new file mode 100644 index 00000000..34b11317 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java @@ -0,0 +1,155 @@ +package org.leavesmc.leaves.neo_command.bot.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.adventure.PaperAdventure; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +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.ArgumentNode; +import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.neo_command.CustomArgumentNode; +import org.leavesmc.leaves.neo_command.bot.BotSubcommand; +import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +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 net.minecraft.network.chat.Component.literal; + +public class RemoveCommand extends BotSubcommand { + + public RemoveCommand() { + super("remove"); + children(BotArgument::new); + } + + private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender sender) { + boolean success = BotList.INSTANCE.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false); + if (!success) { + sender = sender == null ? Bukkit.getConsoleSender() : sender; + sender.sendMessage(text("Bot remove canceled by a plugin", RED)); + } + return success; + } + + private static class BotArgument extends CustomArgumentNode { + + public BotArgument() { + super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + children(RemoveTimeArgument::new); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + ServerBot bot = context.getCustomArgument(BotArgument.class); + return removeBot(bot, context.getSender()); + } + } + + private static class RemoveTimeArgument extends ArgumentNode { + + private RemoveTimeArgument() { + super("remove_time", StringArgumentType.word()); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + String removeTimeStr = context.getArgument("remove_time", String.class); + int removeTimeSeconds = parseRemoveTime(removeTimeStr); + ServerBot bot = context.getCustomArgument(BotArgument.class); + CommandSender sender = context.getSender(); + + boolean isReschedule = bot.removeTaskId != -1; + + if (isReschedule) { + Bukkit.getScheduler().cancelTask(bot.removeTaskId); + } + bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> { + bot.removeTaskId = -1; + removeBot(bot, sender); + }, removeTimeSeconds * 20L).getTaskId(); + + sender.sendMessage(join(spaces(), + text("Bot", GRAY), + PaperAdventure.asAdventure(bot.getDisplayName()), + text("scheduled for removal in", GRAY), + text(formatSeconds(removeTimeSeconds), AQUA), + text(isReschedule ? "(rescheduled)" : "", GRAY) + )); + return true; + } + + private static int parseRemoveTime(String timeStr) throws CommandSyntaxException { + if (timeStr == null || timeStr.trim().isEmpty()) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + + if (!timeStr.matches("^[\\d\\shmsHMS]+$")) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("Invalid time format: " + timeStr) + ); + } + + String remaining = timeStr.replaceAll("\\d+[hmsHMS]", "").trim(); + if (!remaining.isEmpty() && remaining.matches(".*\\d+.*")) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("Found trailing numbers without unit: " + timeStr) + ); + } + + Matcher matcher = Pattern.compile("(\\d+)([hmsHMS])").matcher(timeStr); + int seconds = 0; + boolean foundMatch = false; + + while (matcher.find()) { + foundMatch = true; + int value = Integer.parseInt(matcher.group(1)); + switch (matcher.group(2).toLowerCase()) { + case "h": seconds += value * 3600; break; + case "m": seconds += value * 60; break; + case "s": seconds += value; break; + } + } + + if (!foundMatch) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("No valid time units found in: " + timeStr) + ); + } + + return seconds; + } + + private static @NotNull String formatSeconds(int totalSeconds) { + int h = totalSeconds / 3600; + int m = (totalSeconds % 3600) / 60; + int s = totalSeconds % 60; + StringBuilder sb = new StringBuilder(); + if (h > 0) { + sb.append(h).append("h"); + } + if (m > 0) { + sb.append(m).append("m"); + } + if (s > 0) { + sb.append(s).append("s"); + } + if (sb.isEmpty()) { + sb.append("0s"); + } + return sb.toString(); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java index f3a32bd8..0c15afbc 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java @@ -32,7 +32,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotArgument extends CustomArgumentNode { - public BotArgument() { + private BotArgument() { super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); } @@ -42,16 +42,17 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE 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; + boolean success = botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true); + if (success) { + sender.sendMessage(join(spaces(), + text("Successfully saved bot", NamedTextColor.GRAY), + asAdventure(bot.getDisplayName()), + text("as " + bot.createState.realName(), NamedTextColor.GRAY) + )); + } else { + sender.sendMessage(text("Bot save canceled by a plugin", NamedTextColor.RED)); } - sender.sendMessage(join(spaces(), - text("Successfully saved bot", NamedTextColor.GRAY), - asAdventure(bot.getDisplayName()), - text("as " + bot.createState.realName(), NamedTextColor.GRAY) - )); - return true; + return success; } } } From ef6c8205e02faa6b24926b3f59a2305ee00a877e Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 12:52:30 +0800 Subject: [PATCH 09/29] feat: add show all config --- .../org/leavesmc/leaves/bot/ServerBot.java | 4 ++++ .../bot/subcommands/ConfigCommand.java | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java index faa48bf7..3a50a140 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java @@ -673,6 +673,10 @@ public > AbstractBotConfig g return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config.getName())); } + public Collection> getAllConfigs() { + return configs.values(); + } + public > O getConfigValue(@NotNull AbstractBotConfig config) { return this.getConfig(config).getValue(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java index f5aad795..c609e0d4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.commands.CommandSourceStack; +import org.bukkit.command.CommandSender; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; @@ -15,6 +16,7 @@ import org.leavesmc.leaves.neo_command.LiteralNode; import org.leavesmc.leaves.neo_command.bot.BotSubcommand; +import java.util.Collection; import java.util.function.Supplier; import static io.papermc.paper.adventure.PaperAdventure.asAdventure; @@ -53,6 +55,26 @@ protected BotArgument() { public static @NotNull ServerBot getBot(@NotNull CommandContext context) throws CommandSyntaxException { return context.getCustomArgument(BotArgument.class); } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + ServerBot bot = BotArgument.getBot(context); + CommandSender sender = context.getSender(); + Collection> botConfigs = bot.getAllConfigs(); + sender.sendMessage(join(spaces(), + text("Bot", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("configs:", GRAY) + )); + for (AbstractBotConfig botConfig : botConfigs) { + sender.sendMessage(join(spaces(), + botConfig.getNameComponent(), + text("=", GRAY), + text(String.valueOf(botConfig.getValue()), AQUA) + )); + } + return true; + } } private static class ConfigNode extends LiteralNode { From d0fb999ec6e114f167d338c4749992b72fabdc57 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 15:13:29 +0800 Subject: [PATCH 10/29] feat: finish leaves command --- .../0055-No-block-update-command.patch | 22 +-- ...item-drops-due-to-update-suppression.patch | 4 +- .../0138-Lithium-Sleeping-Block-Entity.patch | 4 +- ...003-Leaves-Server-Config-And-Command.patch | 18 -- .../org/leavesmc/leaves/LeavesConfig.java | 52 +++-- .../leaves/bot/ServerBotGameMode.java | 4 +- .../bot/agent/actions/AbstractBotAction.java | 4 +- .../agent/actions/AbstractTimerBotAction.java | 4 +- .../agent/actions/AbstractUseBotAction.java | 2 +- .../bot/agent/actions/ServerLookAction.java | 2 +- .../bot/agent/actions/ServerMoveAction.java | 4 +- .../agent/actions/ServerRotationAction.java | 2 +- .../bot/agent/configs/AbstractBotConfig.java | 4 +- .../agent/configs/AlwaysSendDataConfig.java | 2 +- .../bot/agent/configs/LocatorBarConfig.java | 2 +- .../configs/SimulationDistanceConfig.java | 2 +- .../bot/agent/configs/SkipSleepConfig.java | 2 +- .../bot/agent/configs/SpawnPhantomConfig.java | 2 +- .../bot/agent/configs/TickTypeConfig.java | 2 +- .../ArgumentNode.java | 2 +- .../leaves/command/CommandArgument.java | 67 ------- .../leaves/command/CommandArgumentResult.java | 92 --------- .../leaves/command/CommandArgumentType.java | 59 ------ .../CommandContext.java | 4 +- .../{neo_command => command}/CommandNode.java | 2 +- .../CommandUtils.java | 9 +- .../CustomArgumentNode.java | 2 +- .../CustomArgumentType.java | 2 +- .../leaves/command/LeavesCommand.java | 38 ---- .../leaves/command/LeavesCommandUtil.java | 181 ------------------ .../leaves/command/LeavesRootCommand.java | 126 ------------ .../leaves/command/LeavesSubcommand.java | 7 - .../command/LeavesSuggestionBuilder.java | 49 ----- .../command/LeavesSuggestionCommand.java | 15 -- .../{neo_command => command}/LiteralNode.java | 2 +- .../WrappedArgument.java | 2 +- .../bot/BotArgument.java | 6 +- .../bot/BotCommand.java | 30 ++- .../bot/BotSubcommand.java | 4 +- .../bot/subcommands/ActionCommand.java | 16 +- .../bot/subcommands/ConfigCommand.java | 12 +- .../bot/subcommands/CreateCommand.java | 8 +- .../bot/subcommands/ListCommand.java | 8 +- .../bot/subcommands/LoadCommand.java | 8 +- .../bot/subcommands/RemoveCommand.java | 12 +- .../bot/subcommands/SaveCommand.java | 10 +- .../bot/subcommands/action/ListCommand.java | 8 +- .../bot/subcommands/action/StartCommand.java | 10 +- .../bot/subcommands/action/StopCommand.java | 10 +- .../leaves/LeavesCommand.java | 32 ++-- .../command/leaves/LeavesSubcommand.java | 22 +++ .../subcommands/BlockUpdateCommand.java | 101 ++++++++++ .../leaves/subcommands/ConfigCommand.java | 27 +-- .../leaves/subcommands/CounterCommand.java | 170 ++++++++++++++++ .../leaves/subcommands/ReloadCommand.java | 30 +++ .../subcommands/ReportCommand.java | 97 ++++++---- .../leaves/subcommands/UpdateCommand.java | 31 +++ .../subcommands/BlockUpdateCommand.java | 33 ---- .../command/subcommands/ConfigCommand.java | 92 --------- .../command/subcommands/CounterCommand.java | 106 ---------- .../command/subcommands/ReloadCommand.java | 20 -- .../command/subcommands/UpdateCommand.java | 16 -- 62 files changed, 585 insertions(+), 1131 deletions(-) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/ArgumentNode.java (98%) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/CommandContext.java (97%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/CommandNode.java (98%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/CommandUtils.java (92%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/CustomArgumentNode.java (97%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/CustomArgumentType.java (93%) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/LiteralNode.java (96%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/WrappedArgument.java (98%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/BotArgument.java (92%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/BotCommand.java (56%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/BotSubcommand.java (79%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/ActionCommand.java (65%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/ConfigCommand.java (93%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/CreateCommand.java (95%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/ListCommand.java (94%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/LoadCommand.java (92%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/RemoveCommand.java (94%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/SaveCommand.java (86%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/action/ListCommand.java (87%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/action/StartCommand.java (93%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/bot/subcommands/action/StopCommand.java (95%) rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/leaves/LeavesCommand.java (50%) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java rename leaves-server/src/main/java/org/leavesmc/leaves/{neo_command => command}/leaves/subcommands/ConfigCommand.java (84%) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java rename leaves-server/src/main/java/org/leavesmc/leaves/command/{ => leaves}/subcommands/ReportCommand.java (67%) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java diff --git a/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch b/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch index 601f6272..1b07fcea 100644 --- a/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch +++ b/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch @@ -5,7 +5,7 @@ Subject: [PATCH] No block update command diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index 5d4eb61af0b0f39a5d4c37f4a303fa24b3a2936d..48bb795216ca3fb301813080de403a048bbfa98c 100644 +index 9cce442c16ced8d9320a5760580ff13f02cbf8f1..6c67c3b9e7c70366c2889932fd4c0265218656d4 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java @@ -381,7 +381,7 @@ public class ServerPlayerGameMode { @@ -13,12 +13,12 @@ index 5d4eb61af0b0f39a5d4c37f4a303fa24b3a2936d..48bb795216ca3fb301813080de403a04 this.level.captureDrops = new java.util.ArrayList<>(); // CraftBukkit end - BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player); -+ BlockState blockState1 = org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update ++ BlockState blockState1 = org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update boolean flag = this.level.removeBlock(pos, false); if (flag) { block.destroy(this.level, pos, blockState1); diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fbe49bc685 100644 +index 6202ea6f6f8e6b751434848fb6551c61162d076b..a8c20ef3be53bd462e4c352a08f4b7201a8af373 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -1089,6 +1089,11 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl @@ -26,7 +26,7 @@ index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fb @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + flags = flags & ~1 | net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE; + } + // Leaves end - no block update @@ -38,7 +38,7 @@ index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fb BlockState blockState = oldState; BlockState blockState1 = currentState; + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + flags = flags & ~1 | net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE; + } + // Leaves end - no block update @@ -51,7 +51,7 @@ index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fb int i = flags & -34; - + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + this.updatePOIOnBlockStateChange(pos, blockState, blockState1); + return; + } @@ -60,19 +60,19 @@ index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fb blockState.updateIndirectNeighbourShapes(this, pos, i, recursionLeft - 1); // Don't call an event for the old block to limit event spam boolean cancelledUpdates = false; // Paper - Fix block place logic diff --git a/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index 16aa9f5996dc6eda95541fddb01e00e41305357a..31ab92e0769aa4ce09da5073ad9b734eeebac9c5 100644 +index 16aa9f5996dc6eda95541fddb01e00e41305357a..6bd7d937bab8baf7c657e689e8a1b4069c207ff9 100644 --- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java @@ -105,6 +105,7 @@ public class PistonBaseBlock extends DirectionalBlock { } private void checkIfExtend(Level level, BlockPos pos, BlockState state) { -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update Direction direction = state.getValue(FACING); boolean neighborSignal = this.getNeighborSignal(level, pos, direction); if (neighborSignal && !state.getValue(EXTENDED)) { diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java -index 263bf2b795057c2d5218bf9cfb684e526601aa77..da1e77ccd8805ac0cb0729720b4a1742da67d35c 100644 +index 8942aa2ca4796c7c36c0955141627ea905e0ec64..2d2b7f3284171517d1e68cef802ae197e2e6f8bb 100644 --- a/net/minecraft/world/level/redstone/NeighborUpdater.java +++ b/net/minecraft/world/level/redstone/NeighborUpdater.java @@ -34,6 +34,11 @@ public interface NeighborUpdater { @@ -80,7 +80,7 @@ index 263bf2b795057c2d5218bf9cfb684e526601aa77..da1e77ccd8805ac0cb0729720b4a1742 LevelAccessor level, Direction direction, BlockPos pos, BlockPos neighborPos, BlockState neighborState, int flags, int recursionLeft ) { + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + flags = flags & ~1 | net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE; + } + // Leaves end - no block update @@ -91,7 +91,7 @@ index 263bf2b795057c2d5218bf9cfb684e526601aa77..da1e77ccd8805ac0cb0729720b4a1742 static void executeUpdate(Level level, BlockState state, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston, BlockPos sourcePos) { // Paper end - Add source block to BlockPhysicsEvent -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update try { // CraftBukkit start org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(state), org.bukkit.craftbukkit.block.CraftBlock.at(level, sourcePos)); // Paper - Add source block to BlockPhysicsEvent diff --git a/leaves-server/minecraft-patches/features/0132-Prevent-loss-of-item-drops-due-to-update-suppression.patch b/leaves-server/minecraft-patches/features/0132-Prevent-loss-of-item-drops-due-to-update-suppression.patch index bb8e2049..c8d405e8 100644 --- a/leaves-server/minecraft-patches/features/0132-Prevent-loss-of-item-drops-due-to-update-suppression.patch +++ b/leaves-server/minecraft-patches/features/0132-Prevent-loss-of-item-drops-due-to-update-suppression.patch @@ -6,13 +6,13 @@ Subject: [PATCH] Prevent loss of item drops due to update suppression when diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index f258bc30014f94243ad832b33dcb6c9acd1f2f08..9a4eb1f8e01517707befa30b3ccacc7c84c0abe9 100644 +index 6c67c3b9e7c70366c2889932fd4c0265218656d4..3cc4ebfb9f083e8872460d6c47ad1d76d2cba990 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java @@ -382,7 +382,18 @@ public class ServerPlayerGameMode { this.level.captureDrops = new java.util.ArrayList<>(); // CraftBukkit end - BlockState blockState1 = org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update + BlockState blockState1 = org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update - boolean flag = this.level.removeBlock(pos, false); + // Leaves start - Prevent loss of item drops due to update suppression when breaking blocks + boolean flag; diff --git a/leaves-server/minecraft-patches/features/0138-Lithium-Sleeping-Block-Entity.patch b/leaves-server/minecraft-patches/features/0138-Lithium-Sleeping-Block-Entity.patch index f57a4304..3c435c1d 100644 --- a/leaves-server/minecraft-patches/features/0138-Lithium-Sleeping-Block-Entity.patch +++ b/leaves-server/minecraft-patches/features/0138-Lithium-Sleeping-Block-Entity.patch @@ -447,13 +447,13 @@ index a63330b232dc41f0a5bb36bb94dfb84f01504699..7fbce8302739ab016f1b64f8227c6d72 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index f31a48530e965f01507c335f50d898ed72767e3c..e5b12f0be3c21b14b1fd8a33b20a9292e3b7b8df 100644 +index 3699a9688c15afb2219e504ce6f3f27ea038b575..fc3517a1f14b72f127ab1e9342750491066a56cc 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -1224,6 +1224,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl int i = flags & -34; // Leaves start - no block update - if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + if (org.leavesmc.leaves.LeavesConfig.performance.sleepingBlockEntity) org.leavesmc.leaves.lithium.common.hopper.HopperHelper.updateHopperOnUpdateSuppression(this, pos, flags, chunkAt, oldState != currentState); // Leaves - Lithium Sleeping Block Entity this.updatePOIOnBlockStateChange(pos, blockState, blockState1); return; diff --git a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch b/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch index 97e25a1a..0bd858fc 100644 --- a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch +++ b/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch @@ -17,24 +17,6 @@ index 62e2d5704c348955bc8284dc2d54c933b7bcdd06..7ef20f0138fad39a1d23edd7b26ddc88 @Override public void executeAsync(final Runnable runnable) { MCUtil.scheduleAsyncTask(this.catching(runnable, "asynchronous")); -diff --git a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -index 5c52b1563d20d7e977a5bb958c18b19dec5c365a..65664441c5692620a8b22513ded497b7951a3245 100644 ---- a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -+++ b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -@@ -106,6 +106,13 @@ public class BukkitCommandNode extends LiteralCommandNode { - List results = null; - Location pos = context.getSource().getLocation(); - try { -+ // Leaves start - custom suggestion -+ if (this.command instanceof org.leavesmc.leaves.command.LeavesSuggestionCommand suggestionCommand) { -+ org.leavesmc.leaves.command.LeavesSuggestionBuilder suggestionBuilder = new org.leavesmc.leaves.command.LeavesSuggestionBuilder(builder.createOffset(builder.getInput().lastIndexOf(' ') + 1)); -+ suggestionCommand.suggest(sender, this.literal, args, pos.clone(), suggestionBuilder); -+ return suggestionBuilder.build(); -+ } -+ // Leaves end - custom suggestion - results = this.command.tabComplete(sender, this.literal, args, pos.clone()); - } catch (CommandException ex) { - sender.sendMessage(Component.text("An internal error occurred while attempting to tab-complete this command", NamedTextColor.RED)); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 32fe51b19323e3c4c56e7f9e621e6e808ee5fe38..2eba1d900b20a781c4bb08caa2b30bfeb2d02b9d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 3bb30b2e..9ad9406b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -7,7 +7,6 @@ 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; import org.bukkit.permissions.Permission; @@ -16,7 +15,6 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Actions; -import org.leavesmc.leaves.command.LeavesCommand; import org.leavesmc.leaves.config.GlobalConfigManager; import org.leavesmc.leaves.config.annotations.GlobalConfig; import org.leavesmc.leaves.config.annotations.GlobalConfigCategory; @@ -30,7 +28,8 @@ 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.bot.BotCommand; +import org.leavesmc.leaves.command.bot.BotCommand; +import org.leavesmc.leaves.command.leaves.LeavesCommand; import org.leavesmc.leaves.profile.LeavesMinecraftSessionService; import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule; import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules; @@ -94,8 +93,7 @@ public static void init(final @NotNull File file) { GlobalConfigManager.init(); - registerCommand("leaves", new LeavesCommand()); - org.leavesmc.leaves.neo_command.leaves.LeavesCommand.INSTANCE.register(); + LeavesCommand.INSTANCE.register(); } public static void reload() { @@ -121,11 +119,6 @@ public static void save() { } } - public static void registerCommand(String name, Command command) { - MinecraftServer.getServer().server.getCommandMap().register(name, "leaves", command); - MinecraftServer.getServer().server.syncCommands(); - } - public static ModifyConfig modify = new ModifyConfig(); @GlobalConfigCategory("modify") @@ -196,10 +189,8 @@ private static class CanUseActionValidator extends BooleanConfigValidator { public void verify(Boolean old, Boolean value) throws IllegalArgumentException { if (old != null && !old.equals(value)) { Bukkit.getOnlinePlayers().stream() - .filter(sender -> - BotCommand.hasPermission(sender) - || BotCommand.hasPermission(sender, "action") - ).forEach(org.bukkit.entity.Player::updateCommands); + .filter(sender -> BotCommand.hasPermission(sender, "action")) + .forEach(org.bukkit.entity.Player::updateCommands); } } } @@ -213,8 +204,7 @@ public void verify(Boolean old, Boolean value) throws IllegalArgumentException { if (old != null && !old.equals(value)) { Bukkit.getOnlinePlayers().stream() .filter(sender -> - BotCommand.hasPermission(sender) - || BotCommand.hasPermission(sender, "config") + BotCommand.hasPermission(sender, "config") ).forEach(org.bukkit.entity.Player::updateCommands); } } @@ -229,9 +219,7 @@ public void verify(Boolean old, Boolean value) throws IllegalArgumentException { if (old != null && !old.equals(value)) { Bukkit.getOnlinePlayers().stream() .filter(sender -> - BotCommand.hasPermission(sender) - || BotCommand.hasPermission(sender, "save") - || BotCommand.hasPermission(sender, "load") + BotCommand.hasPermission(sender, "save") || BotCommand.hasPermission(sender, "load") ).forEach(org.bukkit.entity.Player::updateCommands); } } @@ -678,9 +666,20 @@ public void verify(Boolean old, Boolean value) throws IllegalArgumentException { } } - @GlobalConfig(value = "no-block-update-command") + @GlobalConfig(value = "no-block-update-command", validator = NoBlockUpdateValidator.class) public boolean noBlockUpdateCommand = false; + private static class NoBlockUpdateValidator extends BooleanConfigValidator { + @Override + public void verify(Boolean old, Boolean value) throws IllegalArgumentException { + if (old != null && !old.equals(value)) { + Bukkit.getOnlinePlayers().stream() + .filter(sender -> LeavesCommand.hasPermission(sender, "blockupdate")) + .forEach(org.bukkit.entity.Player::updateCommands); + } + } + } + @GlobalConfig("no-tnt-place-update") public boolean noTNTPlaceUpdate = false; @@ -709,9 +708,20 @@ public void verify(Boolean old, Boolean value) throws IllegalArgumentException { public static class HopperCounterConfig { @TransferConfig(value = "modify.hopper-counter", transformer = HopperCounterTransfer.class) @TransferConfig("modify.counter.enable") - @GlobalConfig("enable") + @GlobalConfig(value = "enable", validator = HopperCounterValidator.class) public boolean enable = false; + private static class HopperCounterValidator extends BooleanConfigValidator { + @Override + public void verify(Boolean old, Boolean value) throws IllegalArgumentException { + if (old != null && !old.equals(value)) { + Bukkit.getOnlinePlayers().stream() + .filter(sender -> LeavesCommand.hasPermission(sender, "counter")) + .forEach(org.bukkit.entity.Player::updateCommands); + } + } + } + @TransferConfig("modify.counter.unlimited-speed") @GlobalConfig("unlimited-speed") public boolean unlimitedSpeed = false; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java index bf16fe7f..c636ab69 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java @@ -19,6 +19,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate; + public class ServerBotGameMode extends ServerPlayerGameMode { public ServerBotGameMode(ServerBot bot) { @@ -62,7 +64,7 @@ public boolean destroyBlock(@NotNull BlockPos pos) { this.level.sendBlockUpdated(pos, blockState, blockState, 3); return false; } else { - BlockState blockState1 = org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update + BlockState blockState1 = isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update boolean flag = this.level.removeBlock(pos, false); if (flag) { block.destroy(this.level, pos, blockState1); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index 86286b94..eb798ee2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -10,8 +10,8 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import org.leavesmc.leaves.neo_command.CommandContext; -import org.leavesmc.leaves.neo_command.WrappedArgument; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.WrappedArgument; import org.leavesmc.leaves.util.UpdateSuppressionException; import java.util.ArrayList; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index 9685e47f..15d904ce 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -2,12 +2,12 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import java.util.function.Supplier; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; -import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings; +import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings; public abstract class AbstractTimerBotAction> extends AbstractBotAction { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 1a367cfb..69b8fd9f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import java.util.function.Supplier; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index c65d2199..bbf11568 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -14,7 +14,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; public class ServerLookAction extends AbstractBotAction { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 6ed01137..3d3db621 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -7,13 +7,13 @@ import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import java.util.Arrays; import java.util.Map; import static java.util.stream.Collectors.toMap; -import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings; +import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings; public class ServerMoveAction extends AbstractStateBotAction { private static final Map NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap( diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 7218a740..86f9fdaf 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import java.text.DecimalFormat; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java index 81d05050..7ee528b8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -8,8 +8,8 @@ import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.neo_command.CommandContext; -import org.leavesmc.leaves.neo_command.WrappedArgument; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.WrappedArgument; import java.lang.reflect.Method; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index b82fec5d..01c2ac71 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java index ee3e119a..2a81bad7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java @@ -5,7 +5,7 @@ import net.minecraft.server.waypoints.ServerWaypointManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; public class LocatorBarConfig extends AbstractBotConfig { private boolean value; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 1c6b832f..75d3f481 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -5,7 +5,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import static net.minecraft.network.chat.Component.literal; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index 14e297fd..5577ce2d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; public class SkipSleepConfig extends AbstractBotConfig { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index 6b5dbdde..25ec048f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -5,7 +5,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.neo_command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index 961f6563..109d9930 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -7,7 +7,7 @@ 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.command.CommandContext; public class TickTypeConfig extends AbstractBotConfig { private ServerBot.TickType value; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java similarity index 98% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java index 0f70d0a0..d9b802d2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/ArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.ArgumentBuilder; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java deleted file mode 100644 index bc0c3dca..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiFunction; - -public class CommandArgument { - - public static final CommandArgument EMPTY = new CommandArgument(); - - private static final Pair, String> EMPTY_SUGGESTION_RESULT = Pair.of(List.of(), null); - private static final BiFunction, String>> EMPTY_SUGGESTION = (sender, arg) -> EMPTY_SUGGESTION_RESULT; - - private final List, String>>> suggestions; - private final List> argumentTypes; - - private CommandArgument(CommandArgumentType... argumentTypes) { - this.argumentTypes = List.of(argumentTypes); - this.suggestions = new ArrayList<>(); - for (int i = 0; i < argumentTypes.length; i++) { - suggestions.add(EMPTY_SUGGESTION); - } - } - - public static CommandArgument of(CommandArgumentType... argumentTypes) { - return new CommandArgument(argumentTypes); - } - - public List> getArgumentTypes() { - return argumentTypes; - } - - public CommandArgument setSuggestion(int n, BiFunction, String>> suggestion) { - this.suggestions.set(n, suggestion); - return this; - } - - public CommandArgument setSuggestion(int n, Pair, String> suggestion) { - return this.setSuggestion(n, (sender, arg) -> suggestion); - } - - public CommandArgument setSuggestion(int n, List tabComplete) { - return this.setSuggestion(n, Pair.of(tabComplete, null)); - } - - public Pair, String> suggestion(int n, CommandSender sender, String arg) { - if (suggestions.size() > n) { - return suggestions.get(n).apply(sender, arg); - } else { - return EMPTY_SUGGESTION.apply(sender, arg); - } - } - - public CommandArgumentResult parse(int index, String @NotNull [] args) { - Object[] result = new Object[argumentTypes.size()]; - Arrays.fill(result, null); - for (int i = index, j = 0; i < args.length && j < result.length; i++, j++) { - result[j] = argumentTypes.get(j).parse(args[i]); - } - return new CommandArgumentResult(new ArrayList<>(Arrays.asList(result))); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java deleted file mode 100644 index a56cd7b8..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.leavesmc.leaves.command; - -import net.minecraft.core.BlockPos; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Objects; - -public class CommandArgumentResult { - - private final List result; - - public CommandArgumentResult(List result) { - this.result = result; - } - - public int readInt(int def) { - return Objects.requireNonNullElse(read(Integer.class), def); - } - - public double readDouble(double def) { - return Objects.requireNonNullElse(read(Double.class), def); - } - - public float readFloat(float def) { - return Objects.requireNonNullElse(read(Float.class), def); - } - - public String readString(String def) { - return Objects.requireNonNullElse(read(String.class), def); - } - - public boolean readBoolean(boolean def) { - return Objects.requireNonNullElse(read(Boolean.class), def); - } - - public BlockPos readPos() { - Integer[] pos = {read(Integer.class), read(Integer.class), read(Integer.class)}; - for (Integer po : pos) { - if (po == null) { - return null; - } - } - return new BlockPos(pos[0], pos[1], pos[2]); - } - - public @Nullable Vector readVector() { - Double[] pos = {read(Double.class), read(Double.class), read(Double.class)}; - for (Double po : pos) { - if (po == null) { - return null; - } - } - return new Vector(pos[0], pos[1], pos[2]); - } - - public @NotNull Vector readVectorYZ(double x) { - Double[] pos = {x, read(Double.class), read(Double.class)}; - for (Double po : pos) { - if (po == null) { - throw new IllegalArgumentException("Failed to read vector!"); - } - } - return new Vector(pos[0], pos[1], pos[2]); - } - - public Object readObject() { - if (result.isEmpty()) { - return null; - } - return result.removeFirst(); - } - - public T read(Class tClass, T def) { - return Objects.requireNonNullElse(read(tClass), def); - } - - public T read(Class tClass) { - if (result.isEmpty()) { - return null; - } - - Object obj = result.removeFirst(); - if (tClass.isInstance(obj)) { - return tClass.cast(obj); - } else { - return null; - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java deleted file mode 100644 index b39f6f46..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Function; - -public abstract class CommandArgumentType { - - public static final CommandArgumentType STRING = CommandArgumentType.string(); - public static final CommandArgumentType INTEGER = CommandArgumentType.of(Integer.class, Integer::parseInt); - public static final CommandArgumentType DOUBLE = CommandArgumentType.of(Double.class, Double::parseDouble); - public static final CommandArgumentType FLOAT = CommandArgumentType.of(Float.class, Float::parseFloat); - public static final CommandArgumentType BOOLEAN = CommandArgumentType.of(Boolean.class, Boolean::parseBoolean); - - private final Class type; - - private CommandArgumentType(Class type) { - this.type = type; - } - - @NotNull - @Contract(value = "_, _ -> new", pure = true) - public static CommandArgumentType of(Class type, Function parse) { - return new CommandArgumentType<>(type) { - @Override - public E parse(@NotNull String arg) { - try { - return parse.apply(arg); - } catch (Exception ignore) { - return null; - } - } - }; - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static > CommandArgumentType ofEnum(Class type) { - return of(type, (string -> Enum.valueOf(type, string.toUpperCase()))); - } - - @NotNull - @Contract(value = " -> new", pure = true) - private static CommandArgumentType string() { - return new CommandArgumentType<>(String.class) { - @Override - public String parse(@NotNull String arg) { - return arg; - } - }; - } - - public Class getType() { - return type; - } - - public abstract E parse(@NotNull String arg); -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java similarity index 97% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java index d075ccc7..8d572553 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.Command; import com.mojang.brigadier.RedirectModifier; @@ -12,7 +12,7 @@ import java.util.List; -import static org.leavesmc.leaves.neo_command.CommandNode.getNameForNode; +import static org.leavesmc.leaves.command.CommandNode.getNameForNode; @SuppressWarnings({"ClassCanBeRecord", "unused"}) public class CommandContext { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java similarity index 98% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java index 41859e21..ccf1449e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java similarity index 92% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java index d6a04cf0..8077fb94 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CommandUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.google.common.base.Functions; import com.google.common.collect.Iterables; @@ -23,6 +23,13 @@ public class CommandUtils { + public static void registerPermissions(String base, @NotNull List children) { + List permissions = new ArrayList<>(); + permissions.add(base); + permissions.addAll(children.stream().map((it) -> base + "." + it.getName()).toList()); + registerPermissions(permissions); + } + public static void registerPermissions(@NotNull List permissions) { PluginManager pluginManager = Bukkit.getServer().getPluginManager(); for (String perm : permissions) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java similarity index 97% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java index 75fdc784..6d302270 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java similarity index 93% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java index 458ac711..3e44ede1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/CustomArgumentType.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java deleted file mode 100644 index caea88aa..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.leavesmc.leaves.command; - -import net.minecraft.Util; -import org.leavesmc.leaves.command.subcommands.BlockUpdateCommand; -import org.leavesmc.leaves.command.subcommands.ConfigCommand; -import org.leavesmc.leaves.command.subcommands.CounterCommand; -import org.leavesmc.leaves.command.subcommands.ReloadCommand; -import org.leavesmc.leaves.command.subcommands.ReportCommand; -import org.leavesmc.leaves.command.subcommands.UpdateCommand; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public final class LeavesCommand extends LeavesRootCommand { - - public static final String BASE_PERM = "bukkit.command.leaves."; - - // subcommand label -> subcommand - private static final Map SUBCOMMANDS = Util.make(() -> { - final Map, LeavesSubcommand> commands = new HashMap<>(); - commands.put(Set.of("config"), new ConfigCommand()); - commands.put(Set.of("update"), new UpdateCommand()); - commands.put(Set.of("counter"), new CounterCommand()); - commands.put(Set.of("reload"), new ReloadCommand()); - commands.put(Set.of("report"), new ReportCommand()); - commands.put(Set.of("blockupdate"), new BlockUpdateCommand()); - - 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)); - }); - - public LeavesCommand() { - super("leaves", "Leaves related commands", "bukkit.command.leaves", SUBCOMMANDS); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java deleted file mode 100644 index afb48b7e..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java +++ /dev/null @@ -1,181 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.google.common.base.Functions; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import net.minecraft.resources.ResourceLocation; -import org.bukkit.command.CommandSender; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.framework.qual.DefaultQualifier; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@DefaultQualifier(NonNull.class) -public class LeavesCommandUtil { - - private LeavesCommandUtil() { - } - - // Code from Mojang - copyright them - public static List getListMatchingLast( - final CommandSender sender, - final String[] args, - final String... matches - ) { - return getListMatchingLast(sender, args, Arrays.asList(matches)); - } - - public static boolean matches(final String s, final String s1) { - return s1.regionMatches(true, 0, s, 0, s.length()); - } - - public static List getListMatchingLast( - final CommandSender sender, - final String[] strings, - final Collection collection - ) { - return getListMatchingLast(sender, strings, collection, LeavesCommand.BASE_PERM, "bukkit.command.leaves"); - } - - public static List getListMatchingLast( - final CommandSender sender, - final String[] strings, - final Collection collection, - final String basePermission, - final String overridePermission - ) { - String last = strings[strings.length - 1]; - ArrayList results = Lists.newArrayList(); - - if (!collection.isEmpty()) { - - for (String s1 : Iterables.transform(collection, Functions.toStringFunction())) { - if (matches(last, s1) && (sender.hasPermission(basePermission + s1) || sender.hasPermission(overridePermission))) { - results.add(s1); - } - } - - if (results.isEmpty()) { - for (Object object : collection) { - if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { - results.add(String.valueOf(object)); - } - } - } - } - - return results; - } - // end copy stuff - - public static List getListClosestMatchingLast( - final CommandSender sender, - final String last, - final Collection collection, - final String overridePermission - ) { - ArrayList candidates = Lists.newArrayList(); - - if (collection.isEmpty() || !sender.hasPermission(overridePermission)) { - return Collections.emptyList(); - } - - 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 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 Wikipedia: Damerau–Levenshtein distance - * - * @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 && s2 != 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 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) { - private static Candidate of(String item, int score) { - return new Candidate(item, score); - } - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java deleted file mode 100644 index 90bda53e..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.leavesmc.leaves.command; - -import it.unimi.dsi.fastutil.Pair; -import net.kyori.adventure.text.Component; -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 org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.RED; - -public abstract class LeavesRootCommand extends Command implements LeavesSuggestionCommand { - - protected final String basePermission; - protected final Map subcommands; - - protected LeavesRootCommand( - @NotNull String name, - @NotNull String description, - @NotNull String basePermission, - @NotNull Map subCommands - ) { - super(name, description, String.format("/%s [%s]", name, String.join(" | ", subCommands.keySet())), Collections.emptyList()); - this.basePermission = basePermission; - this.subcommands = subCommands; - - final List permissions = new ArrayList<>(); - permissions.add(basePermission); - permissions.addAll(subCommands.keySet().stream().map(s -> basePermission + "." + s).toList()); - this.setPermission(String.join(";", permissions)); - final PluginManager pluginManager = Bukkit.getServer().getPluginManager(); - for (final String perm : permissions) { - if (pluginManager.getPermission(perm) == null) { - pluginManager.addPermission(new Permission(perm, PermissionDefault.OP)); - } - } - } - - protected boolean testPermission(final CommandSender sender, final String permission) { - if (sender.hasPermission(basePermission) || sender.hasPermission(basePermission + "." + permission)) { - return true; - } - sender.sendMessage(Bukkit.permissionMessage()); - return false; - } - - @Override - public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { - if (!testPermission(sender) || !isEnabled()) { - return true; - } - - if (args.length == 0) { - sender.sendMessage(unknownMessage()); - return true; - } - final Pair subCommand = resolveCommand(args[0]); - - if (subCommand == null) { - sender.sendMessage(unknownMessage()); - return true; - } - - if (!testPermission(sender, subCommand.first())) { - return true; - } - final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length); - subCommand.second().execute(sender, subCommand.first(), choppedArgs); - return true; - } - - @Override - public void suggest(final @NotNull CommandSender sender, final @NotNull String alias, final @NotNull String @NotNull [] args, final @Nullable Location location, @NotNull LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (!testPermission(sender) || !isEnabled()) { - return; - } - if (args.length <= 1) { - LeavesCommandUtil.getListMatchingLast(sender, args, usableSubcommands(), basePermission + ".", basePermission).forEach(builder::suggest); - return; - } - final @Nullable Pair subCommand = resolveCommand(args[0]); - if (subCommand != null) { - subCommand.second().suggest(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length), location, builder); - } - } - - public Component unknownMessage() { - return text(String.format("Usage: /%s [%s]", this.getName(), String.join(" | ", usableSubcommands())), RED); - } - - @Nullable - public Pair resolveCommand(String label) { - label = label.toLowerCase(Locale.ENGLISH); - LeavesSubcommand subCommand = subcommands.get(label); - - if (subCommand != null && subCommand.isEnabled()) { - return Pair.of(label, subCommand); - } - - return null; - } - - public Collection usableSubcommands() { - List subcommandList = new ArrayList<>(); - for (var entry : subcommands.entrySet()) { - if (entry.getValue().isEnabled()) { - subcommandList.add(entry.getKey()); - } - } - return subcommandList; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java deleted file mode 100644 index c026b634..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.bukkit.command.CommandSender; - -public interface LeavesSubcommand extends LeavesSuggestionCommand { - void execute(CommandSender sender, String subCommand, String[] args); -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java deleted file mode 100644 index 1eb02281..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.mojang.brigadier.Message; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; - -import java.util.concurrent.CompletableFuture; - -public class LeavesSuggestionBuilder { - - private SuggestionsBuilder vanillaBuilder; - - public LeavesSuggestionBuilder(SuggestionsBuilder builder) { - this.vanillaBuilder = builder; - } - - public CompletableFuture build() { - return vanillaBuilder.buildFuture(); - } - - public LeavesSuggestionBuilder suggest(String text) { - vanillaBuilder.suggest(text); - return this; - } - - public LeavesSuggestionBuilder suggest(String text, Message tooltip) { - vanillaBuilder.suggest(text, tooltip); - return this; - } - - public LeavesSuggestionBuilder suggest(int value) { - vanillaBuilder.suggest(value); - return this; - } - - public LeavesSuggestionBuilder suggest(int value, Message tooltip) { - vanillaBuilder.suggest(value, tooltip); - return this; - } - - public LeavesSuggestionBuilder createOffset(int start) { - vanillaBuilder = vanillaBuilder.createOffset(start); - return this; - } - - public String getInput() { - return vanillaBuilder.getInput(); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java deleted file mode 100644 index ed0f1c5f..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface LeavesSuggestionCommand { - default void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - } - - default boolean isEnabled() { - return true; - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java similarity index 96% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java index 94eb69a9..96d80637 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/LiteralNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.ArgumentBuilder; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java similarity index 98% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java index cda1a019..db8e6747 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/WrappedArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command; +package org.leavesmc.leaves.command; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.RequiredArgumentBuilder; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java similarity index 92% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java index ee16c072..21bd2202 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot; +package org.leavesmc.leaves.command.bot; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; @@ -11,8 +11,8 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.Bot; import org.leavesmc.leaves.entity.bot.CraftBot; -import org.leavesmc.leaves.neo_command.CommandContext; -import org.leavesmc.leaves.neo_command.CustomArgumentType; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CustomArgumentType; import java.util.Collection; import java.util.concurrent.CompletableFuture; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java similarity index 56% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java index ce526286..c4f846c6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java @@ -1,22 +1,19 @@ -package org.leavesmc.leaves.neo_command.bot; +package org.leavesmc.leaves.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.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.RemoveCommand; -import org.leavesmc.leaves.neo_command.bot.subcommands.SaveCommand; - -import java.util.ArrayList; -import java.util.List; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; +import org.leavesmc.leaves.command.bot.subcommands.ConfigCommand; +import org.leavesmc.leaves.command.bot.subcommands.CreateCommand; +import org.leavesmc.leaves.command.bot.subcommands.ListCommand; +import org.leavesmc.leaves.command.bot.subcommands.LoadCommand; +import org.leavesmc.leaves.command.bot.subcommands.RemoveCommand; +import org.leavesmc.leaves.command.bot.subcommands.SaveCommand; + +import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; public class BotCommand extends LiteralNode { public static final BotCommand INSTANCE = new BotCommand(); @@ -37,10 +34,7 @@ private BotCommand() { @Override protected ArgumentBuilder compile() { - List permissions = new ArrayList<>(); - permissions.add(PERM_BASE); - permissions.addAll(this.children.stream().map(CommandNode::getName).toList()); - CommandUtils.registerPermissions(permissions); + registerPermissions(PERM_BASE, this.children); return super.compile(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java similarity index 79% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java index 10998310..f6d215eb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/BotSubcommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java @@ -1,8 +1,8 @@ -package org.leavesmc.leaves.neo_command.bot; +package org.leavesmc.leaves.command.bot; import net.minecraft.commands.CommandSourceStack; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.neo_command.LiteralNode; +import org.leavesmc.leaves.command.LiteralNode; public abstract class BotSubcommand extends LiteralNode { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java similarity index 65% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java index 268efef0..ac3d142f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -1,16 +1,16 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.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.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; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.command.bot.subcommands.action.ListCommand; +import org.leavesmc.leaves.command.bot.subcommands.action.StartCommand; +import org.leavesmc.leaves.command.bot.subcommands.action.StopCommand; public class ActionCommand extends BotSubcommand { @@ -27,7 +27,7 @@ public boolean requires(@NotNull CommandSourceStack source) { public static class BotArgument extends CustomArgumentNode { protected BotArgument() { - super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); children( StartCommand::new, StopCommand::new, diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java similarity index 93% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java index c609e0d4..7247303b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.command.bot.subcommands; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; @@ -11,10 +11,10 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Configs; import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; -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.BotSubcommand; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.Collection; import java.util.function.Supplier; @@ -41,7 +41,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotArgument extends CustomArgumentNode { protected BotArgument() { - super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); Configs.getConfigs().stream() .map(this::configNodeCreator) .forEach(this::children); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java similarity index 95% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index da03268b..b4f51dda 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.command.bot.subcommands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -20,9 +20,9 @@ import org.leavesmc.leaves.bot.BotCreateState; 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.bot.BotSubcommand; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.bot.BotSubcommand; import static net.kyori.adventure.text.Component.text; import static net.minecraft.commands.arguments.DimensionArgument.getDimension; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java similarity index 94% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java index 00952077..6f444ebe 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.command.bot.subcommands; import com.mojang.brigadier.exceptions.CommandSyntaxException; import io.papermc.paper.adventure.PaperAdventure; @@ -16,9 +16,9 @@ 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 org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.List; import java.util.Objects; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java similarity index 92% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java index aebc4efa..00fc8d46 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/LoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.command.bot.subcommands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -11,9 +11,9 @@ 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 org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.Set; import java.util.concurrent.CompletableFuture; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java similarity index 94% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java index 34b11317..a850599b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/RemoveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.command.bot.subcommands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -10,10 +10,10 @@ 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.ArgumentNode; -import org.leavesmc.leaves.neo_command.CommandContext; -import org.leavesmc.leaves.neo_command.CustomArgumentNode; -import org.leavesmc.leaves.neo_command.bot.BotSubcommand; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; import java.util.regex.Matcher; @@ -44,7 +44,7 @@ private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender private static class BotArgument extends CustomArgumentNode { public BotArgument() { - super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); children(RemoveTimeArgument::new); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java similarity index 86% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java index 0c15afbc..28b69dd8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands; +package org.leavesmc.leaves.command.bot.subcommands; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.text.format.NamedTextColor; @@ -9,9 +9,9 @@ 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 org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.bot.BotSubcommand; import static io.papermc.paper.adventure.PaperAdventure.asAdventure; import static net.kyori.adventure.text.Component.join; @@ -33,7 +33,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotArgument extends CustomArgumentNode { private BotArgument() { - super("bot", new org.leavesmc.leaves.neo_command.bot.BotArgument()); + super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java similarity index 87% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java index 54f90df9..2d39b36c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java @@ -1,13 +1,13 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands.action; +package org.leavesmc.leaves.command.bot.subcommands.action; import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; -import org.leavesmc.leaves.neo_command.CommandContext; -import org.leavesmc.leaves.neo_command.LiteralNode; -import org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java similarity index 93% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java index 7611e284..f5db7acb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands.action; +package org.leavesmc.leaves.command.bot.subcommands.action; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; @@ -11,9 +11,9 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; -import org.leavesmc.leaves.neo_command.CommandContext; -import org.leavesmc.leaves.neo_command.LiteralNode; -import org.leavesmc.leaves.neo_command.WrappedArgument; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.WrappedArgument; import java.util.List; import java.util.Map; @@ -26,7 +26,7 @@ import static net.kyori.adventure.text.event.HoverEvent.showText; import static net.kyori.adventure.text.format.NamedTextColor.AQUA; import static net.kyori.adventure.text.format.NamedTextColor.GRAY; -import static org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand.BotArgument.getBot; +import static org.leavesmc.leaves.command.bot.subcommands.ActionCommand.BotArgument.getBot; public class StartCommand extends LiteralNode { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java similarity index 95% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java index d7b7eda1..13aa77ea 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.neo_command.bot.subcommands.action; +package org.leavesmc.leaves.command.bot.subcommands.action; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -10,10 +10,10 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -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.subcommands.ActionCommand; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; import java.util.HashSet; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java similarity index 50% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java index 8da87769..368778ab 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/LeavesCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java @@ -1,32 +1,38 @@ -package org.leavesmc.leaves.neo_command.leaves; +package org.leavesmc.leaves.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 org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand; +import org.leavesmc.leaves.command.leaves.subcommands.ConfigCommand; +import org.leavesmc.leaves.command.leaves.subcommands.CounterCommand; +import org.leavesmc.leaves.command.leaves.subcommands.ReloadCommand; +import org.leavesmc.leaves.command.leaves.subcommands.ReportCommand; +import org.leavesmc.leaves.command.leaves.subcommands.UpdateCommand; -import java.util.ArrayList; -import java.util.List; +import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; public class LeavesCommand extends LiteralNode { public static final LeavesCommand INSTANCE = new LeavesCommand(); private static final String PERM_BASE = "bukkit.command.leaves"; private LeavesCommand() { - super("leaves_new"); - children(ConfigCommand::new); + super("leaves"); + children( + BlockUpdateCommand::new, + ConfigCommand::new, + CounterCommand::new, + ReloadCommand::new, + ReportCommand::new, + UpdateCommand::new + ); } @Override protected ArgumentBuilder compile() { - List permissions = new ArrayList<>(); - permissions.add(PERM_BASE); - permissions.addAll(this.children.stream().map(CommandNode::getName).toList()); - CommandUtils.registerPermissions(permissions); + registerPermissions(PERM_BASE, this.children); return super.compile(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java new file mode 100644 index 00000000..fa20c4c8 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java @@ -0,0 +1,22 @@ +package org.leavesmc.leaves.command.leaves; + +import net.minecraft.commands.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.LiteralNode; + +public abstract class LeavesSubcommand extends LiteralNode { + + protected LeavesSubcommand(String name) { + super(name); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return hasPermission(source.getSender()); + } + + protected boolean hasPermission(CommandSender sender) { + return LeavesCommand.hasPermission(sender, this.name); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java new file mode 100644 index 00000000..f9d5e841 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java @@ -0,0 +1,101 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.commands.CommandSourceStack; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; + +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.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class BlockUpdateCommand extends LeavesSubcommand { + private static boolean noBlockUpdate = false; + + public static boolean isNoBlockUpdate() { + return LeavesConfig.modify.noBlockUpdateCommand && noBlockUpdate; + } + + public BlockUpdateCommand() { + super("blockupdate"); + children( + EnableNode::new, + DisableNode::new + ); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + context.getSender().sendMessage(join(spaces(), + text("Block update is", GRAY), + text(noBlockUpdate ? "disabled" : "enabled", AQUA) + )); + return true; + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.noBlockUpdateCommand && super.requires(source); + } + + private class EnableNode extends LiteralNode { + + private EnableNode() { + super("enable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (!noBlockUpdate) { + sender.sendMessage(join(spaces(), + text("Block update is already", GRAY), + text("enabled", AQUA) + )); + return true; + } + noBlockUpdate = false; + Bukkit.getOnlinePlayers().stream() + .filter(BlockUpdateCommand.this::hasPermission) + .forEach(player -> player.sendMessage(join(spaces(), + text("Block update is", GRAY), + text("enabled", AQUA) + ))); + return true; + } + } + + private class DisableNode extends LiteralNode { + + private DisableNode() { + super("disable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (noBlockUpdate) { + sender.sendMessage(join(spaces(), + text("Block update is already", GRAY), + text("disabled", AQUA) + )); + return true; + } + noBlockUpdate = true; + Bukkit.getOnlinePlayers().stream() + .filter(BlockUpdateCommand.this::hasPermission) + .forEach(player -> player.sendMessage(join(spaces(), + text("Block update is", GRAY), + text("disabled", AQUA) + ))); + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java similarity index 84% rename from leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java index 6e203d93..ea319e4a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/neo_command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -1,19 +1,16 @@ -package org.leavesmc.leaves.neo_command.leaves.subcommands; +package org.leavesmc.leaves.command.leaves.subcommands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.commands.CommandSourceStack; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.command.LeavesCommandUtil; import org.leavesmc.leaves.config.GlobalConfigManager; import org.leavesmc.leaves.config.VerifiedConfig; -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.leaves.LeavesCommand; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import java.util.concurrent.CompletableFuture; @@ -21,20 +18,15 @@ 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; +import static org.leavesmc.leaves.command.CommandUtils.getListClosestMatchingLast; -public class ConfigCommand extends LiteralNode { +public class ConfigCommand extends LeavesSubcommand { public ConfigCommand() { super("config"); children(PathArgument::new); } - @Override - public boolean requires(@NotNull CommandSourceStack source) { - return LeavesCommand.hasPermission(source.getSender(), "config"); - } - private static class PathArgument extends ArgumentNode { public PathArgument() { @@ -93,18 +85,13 @@ public ValueArgument() { @Override protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { String path = context.getArgument(PathArgument.class); - String value = context.getArgumentOrDefault(ValueArgument.class, ""); VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); if (verifiedConfig == null) { return builder .suggest("", net.minecraft.network.chat.Component.literal("This config path does not exist.")) .buildFuture(); } - LeavesCommandUtil.getListMatchingLast( - context.getSender(), - new String[]{value}, - verifiedConfig.validator().valueSuggest() - ).forEach(builder::suggest); + verifiedConfig.validator().valueSuggest().forEach(builder::suggest); return builder.buildFuture(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java new file mode 100644 index 00000000..2fec3238 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java @@ -0,0 +1,170 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.item.DyeColor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; +import org.leavesmc.leaves.util.HopperCounter; + +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.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class CounterCommand extends LeavesSubcommand { + + public CounterCommand() { + super("counter"); + children( + EnableNode::new, + DisableNode::new, + ResetAllNode::new + ); + for (DyeColor color : DyeColor.values()) { + children(() -> new ColorNode(color)); + } + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.hopperCounter.enable && super.requires(source); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + context.getSender().sendMessage(join(spaces(), + text("Hopper counter is", GRAY), + text(HopperCounter.isEnabled() ? "enabled" : "disabled", AQUA) + )); + return true; + } + + private static class EnableNode extends LiteralNode { + + private EnableNode() { + super("enable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (HopperCounter.isEnabled()) { + sender.sendMessage(join(spaces(), + text("Hopper counter is already", GRAY), + text("disabled", AQUA) + )); + return true; + } + HopperCounter.setEnabled(true); + sender.sendMessage(join(spaces(), + text("Hopper counter is now", GRAY), + text("enabled", AQUA) + )); + return true; + } + } + + private static class DisableNode extends LiteralNode { + + private DisableNode() { + super("disable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (!HopperCounter.isEnabled()) { + sender.sendMessage(join(spaces(), + text("Hopper counter is already", GRAY), + text("disabled", AQUA) + )); + return true; + } + HopperCounter.setEnabled(false); + sender.sendMessage(join(spaces(), + text("Hopper counter is now", GRAY), + text("disabled", AQUA) + )); + return true; + } + } + + private static class ResetAllNode extends LiteralNode { + + private ResetAllNode() { + super("reset"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + HopperCounter.resetAll(MinecraftServer.getServer(), false); + context.getSender().sendMessage(text("Restarted all counters", GRAY)); + return true; + } + } + + private static class ColorNode extends LiteralNode { + private final DyeColor color; + private final HopperCounter counter; + + private ColorNode(@NotNull DyeColor color) { + super(color.getName()); + this.color = color; + this.counter = HopperCounter.getCounter(color); + children( + ResetNode::new, + RealtimeNode::new + ); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + displayCounter(context.getSender(), false); + return true; + } + + private void displayCounter(CommandSender sender, boolean realTime) { + for (Component component : counter.format(MinecraftServer.getServer(), realTime)) { + sender.sendMessage(component); + } + } + + private class ResetNode extends LiteralNode { + + private ResetNode() { + super("reset"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + counter.reset(MinecraftServer.getServer()); + context.getSender().sendMessage(join(spaces(), + text("Restarted counter", GRAY), + text(color.getName(), TextColor.color(color.getTextColor())) + )); + return true; + } + } + + private class RealtimeNode extends LiteralNode { + + private RealtimeNode() { + super("realtime"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + displayCounter(context.getSender(), true); + return true; + } + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java new file mode 100644 index 00000000..72be57c2 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java @@ -0,0 +1,30 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; + +public class ReloadCommand extends LeavesSubcommand { + + public ReloadCommand() { + super("reload"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + LeavesConfig.reload(); + CommandSender sender = context.getSender(); + sender.sendMessage(text("Leaves config reload complete", GREEN)); + Bukkit.getOnlinePlayers().stream() + .filter(player -> player.hasPermission("leaves.command.config.notify") && player != sender) + .forEach(player -> player.sendMessage(text("Leaves config reloaded", GREEN))); + return true; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReportCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReportCommand.java similarity index 67% rename from leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReportCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReportCommand.java index 924fa03b..99984ee2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReportCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReportCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.command.subcommands; +package org.leavesmc.leaves.command.leaves.subcommands; import io.papermc.paper.plugin.configuration.PluginMeta; import io.papermc.paper.plugin.entrypoint.Entrypoint; @@ -8,22 +8,18 @@ import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; import net.minecraft.server.MinecraftServer; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.world.flag.FeatureFlagSet; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.command.LeavesCommandUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta; import java.net.URLEncoder; @@ -33,17 +29,43 @@ import java.util.TreeMap; import java.util.concurrent.CompletableFuture; +import static net.kyori.adventure.text.Component.join; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.noSeparators; +import static net.kyori.adventure.text.JoinConfiguration.spaces; import static net.kyori.adventure.text.format.NamedTextColor.AQUA; -import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED; + +public class ReportCommand extends LeavesSubcommand { + private static final String BASE_URL = "https://github.com/LeavesMC/Leaves/issues/new?template="; + private static final String BUG_REPORT_URL = BASE_URL + "1-bug-report.yml&leaves-version=${version}&plugin-list=${plugins}%0a%0a${datapacks}"; + private static final String NOT_VANILLA_URL = BASE_URL + "2-not-vanilla.yml&leaves-version=${version}"; + + public ReportCommand() { + super("report"); + children( + () -> new ReportTypeNode("bug-report", BUG_REPORT_URL), + () -> new ReportTypeNode("not-vanilla", NOT_VANILLA_URL) + ); + } + + private static class ReportTypeNode extends LiteralNode { + private final String url; -public class ReportCommand implements LeavesSubcommand { + private ReportTypeNode(String type, String url) { + super(type); + this.url = url; + } - private static final String BUG_REPORT_URL = "https://github.com/LeavesMC/Leaves/issues/new?template=1-bug-report.yml&leaves-version=${version}&plugin-list=${plugins}%0a%0a${datapacks}"; - private static final String NOT_VANILLA_URL = "https://github.com/LeavesMC/Leaves/issues/new?template=2-not-vanilla.yml&leaves-version=${version}"; - private static final String COMMAND_PERM = "bukkit.command.leaves.report"; + @Override + protected boolean execute(CommandContext context) { + CompletableFuture.runAsync(() -> sendOnSuccess(context.getSender(), url, name)); + return true; + } + } - private static String generatePluginMessage() { + private static @NotNull String generatePluginMessage() { final StringBuilder pluginList = new StringBuilder(); final TreeMap> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -98,7 +120,7 @@ private static String generatePluginMessage() { return pluginList.toString(); } - private static String generateDataPackMessage() { + private static @NotNull String generateDataPackMessage() { final StringBuilder dataPackList = new StringBuilder(); PackRepository packRepository = MinecraftServer.getServer().getPackRepository(); @@ -130,39 +152,30 @@ private static String generateDataPackMessage() { return dataPackList.toString(); } - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Please select a report template: \"bug-report\" or \"not-vanilla\"", RED)); - return; - } - if (args[0].equals("bug-report")) { - CompletableFuture.runAsync(() -> sendOnSuccess(sender, BUG_REPORT_URL, Component.text("Successfully generated report url for \"bug-report\"", AQUA))); - return; - } else if (args[0].equals("not-vanilla")) { - CompletableFuture.runAsync(() -> sendOnSuccess(sender, NOT_VANILLA_URL, Component.text("Successfully generated report url for \"not-vanilla\"", AQUA))); - return; - } - sender.sendMessage(text("The template" + args[0] + " does not exist! Please select a correct template: \"bug-report\" or \"not-vanilla\"", RED)); - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (args.length <= 1) { - LeavesCommandUtil.getListMatchingLast(sender, args, List.of("bug-report", "not-vanilla"), COMMAND_PERM + ".", COMMAND_PERM).forEach(builder::suggest); - } - } - - private void sendOnSuccess(CommandSender sender, String template, Component component) { + private static void sendOnSuccess(@NotNull CommandSender sender, @NotNull String template, String type) { String finalUrl = template .replace("${version}", URLEncoder.encode(Bukkit.getVersionMessage(), StandardCharsets.UTF_8)) .replace("${plugins}", URLEncoder.encode(generatePluginMessage(), StandardCharsets.UTF_8)) .replace("${datapacks}", URLEncoder.encode(generateDataPackMessage(), StandardCharsets.UTF_8)); + Component base = join(noSeparators(), + text("Successfully generated report url for ", GRAY), + text(type, AQUA), + text(",", GRAY) + ); if (sender instanceof ConsoleCommandSender) { - sender.sendMessage(component.append(text(", please copy it as you are running this command in console"))); - sender.sendMessage(text(finalUrl, AQUA).decorate(TextDecoration.UNDERLINED)); + sender.sendMessage(join(spaces(), + base, + text("please open it in your browser:", GRAY), + text(finalUrl, AQUA) + )); } else { - sender.sendMessage(component.append(text(", click this message to open")).decorate(TextDecoration.UNDERLINED).hoverEvent(Component.text("Click to open the report url", NamedTextColor.WHITE)).clickEvent(ClickEvent.openUrl(finalUrl))); + sender.sendMessage(join(spaces(), + base, + text("click here to continue", AQUA) + .decorate(UNDERLINED) + .hoverEvent(text("Open the report url")) + .clickEvent(ClickEvent.openUrl(finalUrl)) + )); } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java new file mode 100644 index 00000000..0193466c --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java @@ -0,0 +1,31 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; +import org.leavesmc.leaves.util.LeavesUpdateHelper; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class UpdateCommand extends LeavesSubcommand { + + public UpdateCommand() { + super("update"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + CommandSender sender = context.getSender(); + if (sender instanceof ConsoleCommandSender) { + sender.sendMessage(text("Trying to update Leaves...", GRAY)); + } else { + sender.sendMessage(text("Trying to update Leaves, see the console for more info", GRAY)); + } + LeavesUpdateHelper.tryUpdateLeaves(); + return true; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java deleted file mode 100644 index 18477f57..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesSubcommand; - -public class BlockUpdateCommand implements LeavesSubcommand { - - private static boolean noBlockUpdate = false; - - public static boolean isNoBlockUpdate() { - return LeavesConfig.modify.noBlockUpdateCommand && noBlockUpdate; - } - - @Override - public void execute(@NotNull CommandSender sender, @NotNull String commandLabel, String @NotNull [] args) { - noBlockUpdate = !noBlockUpdate; - Bukkit.broadcast(Component.join(JoinConfiguration.noSeparators(), - Component.text("Block update status: ", NamedTextColor.GRAY), - Component.text(!noBlockUpdate, noBlockUpdate ? NamedTextColor.AQUA : NamedTextColor.GRAY) - ), "bukkit.command.leaves.blockupdate"); - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.noBlockUpdateCommand; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java deleted file mode 100644 index e5349244..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.command.LeavesCommandUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.config.GlobalConfigManager; -import org.leavesmc.leaves.config.VerifiedConfig; - -import static net.kyori.adventure.text.Component.text; - -public class ConfigCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Leaves Config", NamedTextColor.GRAY)); - return; - } - - VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(args[0]); - if (verifiedConfig == null) { - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.RED), - text("is Not Found.", NamedTextColor.GRAY) - )); - return; - } - - if (args.length > 1) { - try { - verifiedConfig.set(args[1]); - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.AQUA), - text("changed to", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) - )); - Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission("leaves.command.config.notify") && player != sender).forEach( - player -> player.sendMessage(Component.join(JoinConfiguration.spaces(), - text(sender.getName() + ":", NamedTextColor.GRAY), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.AQUA), - text("changed to", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) - )) - ); - } catch (IllegalArgumentException exception) { - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.RED), - text("modify error by", NamedTextColor.GRAY), - text(exception.getMessage(), NamedTextColor.RED) - )); - } - } else { - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.AQUA), - text("value is", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) - )); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String subCommand, String @NotNull [] args, @Nullable Location location, @NotNull LeavesSuggestionBuilder builder) { - if (args.length <= 1) { - String arg = args[0]; - int dotIndex = arg.lastIndexOf("."); - builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2); - LeavesCommandUtil.getListClosestMatchingLast(sender, arg.substring(dotIndex + 1), GlobalConfigManager.getVerifiedConfigSubPaths(arg), "bukkit.command.leaves.config") - .forEach(builder::suggest); - } - if (args.length == 2) { - VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(args[0]); - if (verifiedConfig != null) { - LeavesCommandUtil.getListMatchingLast(sender, args, verifiedConfig.validator().valueSuggest()).forEach(builder::suggest); - } else { - builder.suggest(""); - } - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java deleted file mode 100644 index f2f87cd9..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextColor; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.item.DyeColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesCommandUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.util.HopperCounter; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class CounterCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), - Component.text("Hopper Counter: ", NamedTextColor.GRAY), - Component.text(HopperCounter.isEnabled(), HopperCounter.isEnabled() ? NamedTextColor.AQUA : NamedTextColor.GRAY) - )); - } - - if (!HopperCounter.isEnabled()) { - if (args[0].equals("enable")) { - HopperCounter.setEnabled(true); - sender.sendMessage(Component.text("Hopper Counter now is enabled", NamedTextColor.AQUA)); - } else { - sender.sendMessage(Component.text("Hopper Counter is not enabled", NamedTextColor.RED)); - } - } - - DyeColor color = DyeColor.byName(args[0], null); - if (color != null) { - HopperCounter counter = HopperCounter.getCounter(color); - if (args.length < 2) { - displayCounter(sender, counter, false); - return; - } - switch (args[1]) { - case "reset" -> { - counter.reset(MinecraftServer.getServer()); - sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), - Component.text("Restarted "), - Component.text(color.getName(), TextColor.color(color.getTextColor())), - Component.text(" counter") - )); - } - case "realtime" -> displayCounter(sender, counter, true); - } - } - - switch (args[0]) { - case "reset" -> { - HopperCounter.resetAll(MinecraftServer.getServer(), false); - sender.sendMessage(Component.text("Restarted all counters")); - } - case "disable" -> { - HopperCounter.setEnabled(false); - HopperCounter.resetAll(MinecraftServer.getServer(), true); - sender.sendMessage(Component.text("Hopper Counter now is disabled", NamedTextColor.GRAY)); - } - } - } - - private void displayCounter(CommandSender sender, @NotNull HopperCounter counter, boolean realTime) { - for (Component component : counter.format(MinecraftServer.getServer(), realTime)) { - sender.sendMessage(component); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (args.length <= 1) { - if (!HopperCounter.isEnabled()) { - builder.suggest("enable"); - return; - } - - List list = new ArrayList<>(Arrays.stream(DyeColor.values()).map(DyeColor::getName).toList()); - list.add("reset"); - list.add("disable"); - LeavesCommandUtil.getListMatchingLast(sender, args, list).forEach(builder::suggest); - } - if (args.length == 2) { - if (DyeColor.byName(args[0], null) != null) { - LeavesCommandUtil.getListMatchingLast(sender, args, "reset", "realtime").forEach(builder::suggest); - } - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.hopperCounter.enable; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java deleted file mode 100644 index 4697c546..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesSubcommand; - -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.GREEN; - -public class ReloadCommand implements LeavesSubcommand { - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - LeavesConfig.reload(); - sender.sendMessage(text("Leaves config reload complete.", GREEN)); - Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission("leaves.command.config.notify") && player != sender).forEach( - player -> player.sendMessage(text("Leaves config reload complete.", GREEN)) - ); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java deleted file mode 100644 index 4af4c88f..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.command.CommandSender; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.util.LeavesUpdateHelper; - -public class UpdateCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - sender.sendMessage(Component.text("Trying to update Leaves, see the console for more info.", NamedTextColor.GRAY)); - LeavesUpdateHelper.tryUpdateLeaves(); - } -} From a994f8bfc83d3069bbe2db2cb5541b5ca37f6366 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 15:37:22 +0800 Subject: [PATCH 11/29] refactor: refactor command --- .../leavesmc/leaves/command/LiteralNode.java | 18 ------- .../org/leavesmc/leaves/command/RootNode.java | 50 +++++++++++++++++++ .../leaves/command/bot/BotCommand.java | 11 ++-- .../leaves/command/leaves/LeavesCommand.java | 21 ++------ 4 files changed, 56 insertions(+), 44 deletions(-) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java index 96d80637..57f8fd9d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java @@ -1,11 +1,8 @@ package org.leavesmc.leaves.command; -import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.server.MinecraftServer; public class LiteralNode extends CommandNode { @@ -17,19 +14,4 @@ protected LiteralNode(String name) { protected ArgumentBuilder compileBase() { return Commands.literal(name); } - - @SuppressWarnings("unchecked") - public void register() { - MinecraftServer.getServer() - .getCommands() - .getDispatcher() - .register((LiteralArgumentBuilder) compile()); - } - - public void unregister() { - CommandDispatcher dispatcher = MinecraftServer.getServer() - .getCommands() - .getDispatcher(); - dispatcher.getRoot().removeCommand(name); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java new file mode 100644 index 00000000..5066ce25 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java @@ -0,0 +1,50 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.MinecraftServer; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; + +public abstract class RootNode extends LiteralNode { + private final String permissionBase; + + public RootNode(String name, String permissionBase) { + super(name); + this.permissionBase = permissionBase; + } + + @Override + protected ArgumentBuilder compile() { + registerPermissions(permissionBase, this.children); + return super.compile(); + } + + protected static boolean hasPermission(@NotNull CommandSender sender, String subcommand, String permissionBase) { + return sender.hasPermission(permissionBase) || sender.hasPermission(permissionBase + "." + subcommand); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return children.stream().anyMatch(child -> child.requires(source)); + } + + @SuppressWarnings("unchecked") + public void register() { + MinecraftServer.getServer() + .getCommands() + .getDispatcher() + .register((LiteralArgumentBuilder) compile()); + } + + public void unregister() { + CommandDispatcher dispatcher = MinecraftServer.getServer() + .getCommands() + .getDispatcher(); + dispatcher.getRoot().removeCommand(name); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java index c4f846c6..d187e864 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java @@ -4,7 +4,7 @@ import net.minecraft.commands.CommandSourceStack; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.RootNode; import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; import org.leavesmc.leaves.command.bot.subcommands.ConfigCommand; import org.leavesmc.leaves.command.bot.subcommands.CreateCommand; @@ -15,12 +15,12 @@ import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; -public class BotCommand extends LiteralNode { +public class BotCommand extends RootNode { public static final BotCommand INSTANCE = new BotCommand(); private static final String PERM_BASE = "bukkit.command.bot"; private BotCommand() { - super("bot"); + super("bot", PERM_BASE); this.children( ListCommand::new, ConfigCommand::new, @@ -38,11 +38,6 @@ private BotCommand() { return super.compile(); } - @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); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java index 368778ab..e3ee08b6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java @@ -1,10 +1,8 @@ package org.leavesmc.leaves.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.command.LiteralNode; +import org.leavesmc.leaves.command.RootNode; import org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand; import org.leavesmc.leaves.command.leaves.subcommands.ConfigCommand; import org.leavesmc.leaves.command.leaves.subcommands.CounterCommand; @@ -12,14 +10,12 @@ import org.leavesmc.leaves.command.leaves.subcommands.ReportCommand; import org.leavesmc.leaves.command.leaves.subcommands.UpdateCommand; -import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; - -public class LeavesCommand extends LiteralNode { +public class LeavesCommand extends RootNode { public static final LeavesCommand INSTANCE = new LeavesCommand(); private static final String PERM_BASE = "bukkit.command.leaves"; private LeavesCommand() { - super("leaves"); + super("leaves", PERM_BASE); children( BlockUpdateCommand::new, ConfigCommand::new, @@ -30,17 +26,6 @@ private LeavesCommand() { ); } - @Override - protected ArgumentBuilder compile() { - registerPermissions(PERM_BASE, this.children); - return super.compile(); - } - - @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); } From cfafc2638bd1bda1cf021185d079806d67b76954 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 15:44:17 +0800 Subject: [PATCH 12/29] refactor: remove unused check --- .../main/java/org/leavesmc/leaves/command/CommandNode.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java index ccf1449e..28e1470b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java @@ -44,11 +44,7 @@ public String getName() { } protected ArgumentBuilder compile() { - ArgumentBuilder builder = compileBase(); - - if (isMethodOverridden("requires", CommandNode.class)) { - builder = builder.requires(this::requires); - } + ArgumentBuilder builder = compileBase().requires(this::requires); for (CommandNode child : children) { builder = builder.then(child.compile()); From 69ac9cac26d1d8080fe4b743cf524db32bb815ed Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 15:53:50 +0800 Subject: [PATCH 13/29] refactor: refactor --- .../main/java/org/leavesmc/leaves/command/ArgumentNode.java | 6 +++++- .../main/java/org/leavesmc/leaves/command/CommandNode.java | 6 +++++- .../org/leavesmc/leaves/command/CustomArgumentNode.java | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java index d9b802d2..c0e73f8c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java @@ -27,11 +27,15 @@ protected CompletableFuture getSuggestions(final CommandContext con return Suggestions.empty(); } + protected boolean overrideSuggestions() { + return isMethodOverridden("getSuggestions", ArgumentNode.class); + } + @Override protected ArgumentBuilder compileBase() { RequiredArgumentBuilder argumentBuilder = Commands.argument(name, argumentType); - if (isMethodOverridden("getSuggestions", ArgumentNode.class)) { + if (overrideSuggestions()) { argumentBuilder.suggests( (context, builder) -> getSuggestions(new CommandContext(context), builder) ); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java index 28e1470b..033dcc97 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java @@ -50,7 +50,7 @@ public String getName() { builder = builder.then(child.compile()); } - if (isMethodOverridden("execute", CommandNode.class)) { + if (canExecute()) { builder = builder.executes(mojangCtx -> { CommandContext ctx = new CommandContext(mojangCtx); return execute(ctx) ? 1 : 0; @@ -60,6 +60,10 @@ public String getName() { return builder; } + protected boolean canExecute() { + return isMethodOverridden("execute", CommandNode.class); + } + protected boolean isMethodOverridden(String methodName, @NotNull Class baseClass) { for (Method method : getClass().getDeclaredMethods()) { if (method.getName().equals(methodName)) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java index 6d302270..647ecc58 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java @@ -32,7 +32,7 @@ public static T transform(Class> nodeC protected ArgumentBuilder compileBase() { RequiredArgumentBuilder argumentBuilder = (RequiredArgumentBuilder) super.compileBase(); - if (!isMethodOverridden("getSuggestions", ArgumentNode.class)) { + if (overrideSuggestions()) { CustomArgumentType customArgumentType = (CustomArgumentType) TYPES.get(getClass()); argumentBuilder.suggests( (context, builder) -> customArgumentType.getSuggestions(new CommandContext(context), builder) From 6d5576e755615983d998403fcd6ad069e82813b9 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 15:54:34 +0800 Subject: [PATCH 14/29] fix: fix logic --- .../java/org/leavesmc/leaves/command/CustomArgumentNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java index 647ecc58..75188f65 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java @@ -32,7 +32,7 @@ public static T transform(Class> nodeC protected ArgumentBuilder compileBase() { RequiredArgumentBuilder argumentBuilder = (RequiredArgumentBuilder) super.compileBase(); - if (overrideSuggestions()) { + if (!overrideSuggestions()) { CustomArgumentType customArgumentType = (CustomArgumentType) TYPES.get(getClass()); argumentBuilder.suggests( (context, builder) -> customArgumentType.getSuggestions(new CommandContext(context), builder) From 9a7ad6ca98c0fc0580d0eec4b741ca1bbbef0af6 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 16:11:38 +0800 Subject: [PATCH 15/29] refactor: format --- .../java/org/leavesmc/leaves/bot/BotList.java | 7 +- .../leavesmc/leaves/bot/agent/Configs.java | 2 +- .../bot/agent/configs/AbstractBotConfig.java | 16 +-- .../leavesmc/leaves/command/CommandUtils.java | 2 +- .../leaves/command/WrappedArgument.java | 15 +-- .../leaves/command/bot/BotArgument.java | 15 +-- .../bot/subcommands/ActionCommand.java | 2 +- .../bot/subcommands/ConfigCommand.java | 12 +- .../bot/subcommands/CreateCommand.java | 9 +- .../command/bot/subcommands/ListCommand.java | 6 +- .../command/bot/subcommands/LoadCommand.java | 3 +- .../bot/subcommands/RemoveCommand.java | 2 +- .../bot/subcommands/action/StartCommand.java | 2 +- .../bot/subcommands/action/StopCommand.java | 4 +- .../leaves/subcommands/ConfigCommand.java | 111 +++++++++--------- 15 files changed, 103 insertions(+), 105 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java index f0581ef1..9844b32b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java @@ -89,7 +89,12 @@ public ServerBot createNewBot(BotCreateState state) { } public ServerBot loadNewBot(String realName) { - return this.loadNewBot(realName, this.dataStorage); + try { + return this.loadNewBot(realName, this.dataStorage); + } catch (Exception e) { + LOGGER.error("Failed to load bot {}", realName, e); + return null; + } } public ServerBot loadNewBot(String realName, IPlayerDataStorage playerIO) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java index da53cc96..056c1cbf 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java @@ -41,7 +41,7 @@ public class Configs { } @SuppressWarnings("unchecked") - private static > @NotNull E register(AbstractBotConfig instance) { + private static > @NotNull E register(AbstractBotConfig instance) { configs.put(instance.getClass(), instance); return (E) instance; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java index 7ee528b8..16a6e5b7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -19,14 +19,14 @@ import static net.kyori.adventure.text.event.HoverEvent.showText; import static net.kyori.adventure.text.format.NamedTextColor.AQUA; -public abstract class AbstractBotConfig> { +public abstract class AbstractBotConfig> { private final String name; - private final WrappedArgument argument; + private final WrappedArgument argument; private final Supplier creator; protected ServerBot bot; - public AbstractBotConfig(String name, ArgumentType type, Supplier creator) { + public AbstractBotConfig(String name, ArgumentType type, Supplier creator) { this.name = name; this.argument = new WrappedArgument<>(name, type); if (shouldApplySuggestions()) { @@ -39,7 +39,7 @@ public AbstractBotConfig(String name, ArgumentType type, Supplier creator) public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { } - public AbstractBotConfig setBot(ServerBot bot) { + public AbstractBotConfig setBot(ServerBot bot) { this.bot = bot; return this; } @@ -48,11 +48,11 @@ public E create() { return creator.get(); } - public abstract O getValue(); + public abstract Value getValue(); - public abstract void setValue(O value) throws CommandSyntaxException; + public abstract void setValue(Value value) throws CommandSyntaxException; - public abstract O loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; + public abstract Value loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; public List> getExtraData() { return List.of(); @@ -75,7 +75,7 @@ public Component getNameComponent() { return result; } - public WrappedArgument getArgument() { + public WrappedArgument getArgument() { return argument; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java index 8077fb94..8c518f74 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java @@ -58,7 +58,7 @@ public static void registerPermissions(@NotNull List permissions) { candidates.add(Candidate.of(item, damerauLevenshteinDistance(lastLower, itemLower))); } } - candidates.sort(Comparator.comparingInt(c -> c.score)); + candidates.sort(Comparator.comparingInt(Candidate::score)); List results = new ArrayList<>(candidates.size()); for (Candidate candidate : candidates) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java index db8e6747..e41eb5c8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java @@ -44,17 +44,14 @@ public boolean isOptional() { public RequiredArgumentBuilder compile() { RequiredArgumentBuilder builder = Commands.argument(name, type); if (asyncSuggestionProvider != null) { - builder.suggests( - (context, b) -> - asyncSuggestionProvider.getSuggestions(new CommandContext(context), b) + builder.suggests((context, b) -> + asyncSuggestionProvider.getSuggestions(new CommandContext(context), b) ); } else if (suggestionApplier != null) { - builder.suggests( - (context, b) -> { - suggestionApplier.applySuggestions(new CommandContext(context), b); - return CompletableFuture.completedFuture(b.build()); - } - ); + builder.suggests((context, b) -> { + suggestionApplier.applySuggestions(new CommandContext(context), b); + return CompletableFuture.completedFuture(b.build()); + }); } return builder; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java index 21bd2202..ea55e25a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java @@ -6,11 +6,8 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.network.chat.Component; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; +import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.entity.bot.Bot; -import org.leavesmc.leaves.entity.bot.CraftBot; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.CustomArgumentType; @@ -25,25 +22,25 @@ public ArgumentType getBaseArgumentType() { @Override public ServerBot transform(String value) throws CommandSyntaxException { - CraftBot craftBot = (CraftBot) Bukkit.getBotManager().getBot(value); - if (craftBot == null) { + ServerBot bot = BotList.INSTANCE.getBotByName(value); + if (bot == null) { throw new CommandSyntaxException( CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), Component.literal("Bot with name '" + value + "' does not exist") ); } - return craftBot.getHandle(); + return bot; } @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { - Collection bots = Bukkit.getBotManager().getBots(); + Collection bots = BotList.INSTANCE.bots; if (bots.isEmpty()) { return builder .suggest("", net.minecraft.network.chat.Component.literal("There are no bots in the server, create one first.")) .buildFuture(); } - bots.stream().map(Player::getName).forEach(builder::suggest); + bots.stream().map(ServerBot::getScoreboardName).forEach(builder::suggest); return builder.buildFuture(); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java index ac3d142f..227fbf11 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -26,7 +26,7 @@ public boolean requires(@NotNull CommandSourceStack source) { public static class BotArgument extends CustomArgumentNode { - protected BotArgument() { + private BotArgument() { super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); children( StartCommand::new, diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java index 7247303b..b28f9cd4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java @@ -40,7 +40,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotArgument extends CustomArgumentNode { - protected BotArgument() { + private BotArgument() { super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); Configs.getConfigs().stream() .map(this::configNodeCreator) @@ -77,10 +77,10 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException } } - private static class ConfigNode extends LiteralNode { - private final AbstractBotConfig config; + private static class ConfigNode extends LiteralNode { + private final AbstractBotConfig config; - private ConfigNode(@NotNull AbstractBotConfig config) { + private ConfigNode(@NotNull AbstractBotConfig config) { super(config.getName()); this.config = config; } @@ -100,7 +100,7 @@ private ConfigNode(@NotNull AbstractBotConfig config) { @Override protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { ServerBot bot = BotArgument.getBot(context); - AbstractBotConfig botConfig = bot.getConfig(config); + AbstractBotConfig botConfig = bot.getConfig(config); context.getSender().sendMessage(join(spaces(), text("Bot", GRAY), asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), @@ -114,7 +114,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE private boolean executeSet(CommandContext context) throws CommandSyntaxException { ServerBot bot = BotArgument.getBot(context); - AbstractBotConfig botConfig = bot.getConfig(config); + AbstractBotConfig botConfig = bot.getConfig(config); try { botConfig.setValue(botConfig.loadFromCommand(context)); } catch (ClassCastException e) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index b4f51dda..e095738a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -100,7 +100,7 @@ private static boolean canCreate(CommandSender sender, @NotNull String name) { private static class NameArgument extends ArgumentNode { - public NameArgument() { + private NameArgument() { super("name", StringArgumentType.word()); children(SkinNameArgument::new); } @@ -113,7 +113,7 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException private static class SkinNameArgument extends ArgumentNode { - public SkinNameArgument() { + private SkinNameArgument() { super("skin_name", StringArgumentType.word()); children(WorldArgument::new); } @@ -122,12 +122,11 @@ public SkinNameArgument() { protected boolean execute(CommandContext context) throws CommandSyntaxException { return handleCreateCommand(context); } - } private static class WorldArgument extends ArgumentNode { - public WorldArgument() { + private WorldArgument() { super("world", DimensionArgument.dimension()); children(LocationArgument::new); } @@ -140,7 +139,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class LocationArgument extends ArgumentNode { - public LocationArgument() { + private LocationArgument() { super("location", Vec3Argument.vec3(true)); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java index 6f444ebe..3033a84f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java @@ -56,13 +56,13 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE } protected static @Nullable Component getBotListMessage(@NotNull World world) { - BotList botList = BotList.INSTANCE; - List botsInLevel = botList.bots.stream() + List botsInLevel = BotList.INSTANCE.bots.stream() .filter((bot) -> bot.getBukkitEntity().getWorld().equals(world)) .toList(); if (botsInLevel.isEmpty()) { return null; } + Component botsMsg = botsInLevel.stream() .map(Player::getDisplayName) .map(PaperAdventure::asAdventure) @@ -78,7 +78,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE private static class WorldArgument extends ArgumentNode { - protected WorldArgument() { + private WorldArgument() { super("world", DimensionArgument.dimension()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java index 00fc8d46..2ef59a4b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -37,7 +37,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotNameArgument extends ArgumentNode { - public BotNameArgument() { + private BotNameArgument() { super("bot_name", StringArgumentType.word()); } @@ -60,7 +60,6 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE text("Successfully loaded bot", NamedTextColor.GRAY), asAdventure(bot.getDisplayName()) )); - return true; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java index a850599b..0b154961 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -43,7 +43,7 @@ private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender private static class BotArgument extends CustomArgumentNode { - public BotArgument() { + private BotArgument() { super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); children(RemoveTimeArgument::new); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java index f5db7acb..23159cba 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -63,7 +63,7 @@ private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotA private class ActionLiteralNode extends LiteralNode { private final AbstractBotAction action; - public ActionLiteralNode(@NotNull AbstractBotAction action) { + private ActionLiteralNode(@NotNull AbstractBotAction action) { super(action.getName()); this.action = action; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java index 13aa77ea..d92493de 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java @@ -37,7 +37,7 @@ public StopCommand() { private static class StopIndexArgument extends ArgumentNode { - protected StopIndexArgument() { + private StopIndexArgument() { super("index", IntegerArgumentType.integer(0)); } @@ -90,7 +90,7 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException private static class StopAll extends LiteralNode { - public StopAll() { + private StopAll() { super("all"); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java index ea319e4a..8dddd120 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -29,9 +29,9 @@ public ConfigCommand() { private static class PathArgument extends ArgumentNode { - public PathArgument() { + private PathArgument() { super("path", StringArgumentType.string()); - children(ValueArgument::new); + children(ConfigCommand.ValueArgument::new); } @Override @@ -76,63 +76,64 @@ protected boolean execute(@NotNull CommandContext context) { return verifiedConfig; } - private static class ValueArgument extends ArgumentNode { + } - public ValueArgument() { - super("value", StringArgumentType.greedyString()); - } + private static class ValueArgument extends ArgumentNode { + + private ValueArgument() { + super("value", StringArgumentType.greedyString()); + } - @Override - protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { - String path = context.getArgument(PathArgument.class); - VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); - if (verifiedConfig == null) { - return builder - .suggest("", net.minecraft.network.chat.Component.literal("This config path does not exist.")) - .buildFuture(); - } - verifiedConfig.validator().valueSuggest().forEach(builder::suggest); - return builder.buildFuture(); + @Override + protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + String path = context.getArgument(PathArgument.class); + VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); + if (verifiedConfig == null) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("This config path does not exist.")) + .buildFuture(); } + verifiedConfig.validator().valueSuggest().forEach(builder::suggest); + return builder.buildFuture(); + } - @Override - protected boolean execute(@NotNull CommandContext context) { - VerifiedConfig verifiedConfig = getVerifiedConfig(context); - String path = context.getArgument(PathArgument.class); - String value = context.getArgument(ValueArgument.class); - if (verifiedConfig == null) { - return false; - } - try { - verifiedConfig.set(value); - context.getSender().sendMessage(join(spaces(), - text("Config", GRAY), - text(path, AQUA), - text("changed to", GRAY), - text(verifiedConfig.getString(), AQUA) - )); - Bukkit.getOnlinePlayers() - .stream() - .filter(player -> player.hasPermission("leaves.command.config.notify") && player != context.getSender()) - .forEach( - player -> player.sendMessage(join(spaces(), - text(context.getSender().getName() + ":", GRAY), - text("Config", GRAY), - text(path, AQUA), - text("changed to", GRAY), - text(verifiedConfig.getString(), AQUA) - )) - ); - return true; - } catch (IllegalArgumentException exception) { - context.getSender().sendMessage(join(spaces(), - text("Config", GRAY), - text(path, RED), - text("modify error by", GRAY), - text(exception.getMessage(), RED) - )); - return false; - } + @Override + protected boolean execute(@NotNull CommandContext context) { + VerifiedConfig verifiedConfig = PathArgument.getVerifiedConfig(context); + String path = context.getArgument(PathArgument.class); + String value = context.getArgument(ValueArgument.class); + if (verifiedConfig == null) { + return false; + } + try { + verifiedConfig.set(value); + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, AQUA), + text("changed to", GRAY), + text(verifiedConfig.getString(), AQUA) + )); + Bukkit.getOnlinePlayers() + .stream() + .filter(player -> player.hasPermission("leaves.command.config.notify") && player != context.getSender()) + .forEach( + player -> player.sendMessage(join(spaces(), + text(context.getSender().getName() + ":", GRAY), + text("Config", GRAY), + text(path, AQUA), + text("changed to", GRAY), + text(verifiedConfig.getString(), AQUA) + )) + ); + return true; + } catch (IllegalArgumentException exception) { + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, RED), + text("modify error by", GRAY), + text(exception.getMessage(), RED) + )); + return false; } } } From dfeb9196b7703a82be6caa6947cd22265b73effa Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 16:18:53 +0800 Subject: [PATCH 16/29] fix: fix msg --- .../leaves/command/leaves/subcommands/CounterCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java index 2fec3238..d9e74f29 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java @@ -59,7 +59,7 @@ protected boolean execute(@NotNull CommandContext context) { if (HopperCounter.isEnabled()) { sender.sendMessage(join(spaces(), text("Hopper counter is already", GRAY), - text("disabled", AQUA) + text("enabled", AQUA) )); return true; } From 568bf16b3199e393984cbc0efaa779c6b5b2289a Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Sun, 24 Aug 2025 16:19:53 +0800 Subject: [PATCH 17/29] refactor: better msg --- .../leaves/command/bot/subcommands/CreateCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index e095738a..2812ff18 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -76,7 +76,7 @@ protected static boolean handleCreateCommand(@NotNull CommandContext context) th private static boolean canCreate(CommandSender sender, @NotNull String name) { BotList botList = BotList.INSTANCE; if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { - sender.sendMessage(text("This name is illegal", NamedTextColor.RED)); + sender.sendMessage(text("This name is illegal, bot name must be 4-16 characters and contain only letters, numbers, and underscores.", NamedTextColor.RED)); return false; } @@ -86,7 +86,7 @@ private static boolean canCreate(CommandSender sender, @NotNull String name) { } if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { - sender.sendMessage(text("This name is not allowed", NamedTextColor.RED)); + sender.sendMessage(text("This name is not allowed in this server", NamedTextColor.RED)); return false; } From 5f5dcb5c00634a7e66c486ee7253130d65310e1a Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Mon, 25 Aug 2025 12:18:48 +0800 Subject: [PATCH 18/29] feat: custom bot action --- .../java/org/leavesmc/leaves/LeavesConfig.java | 10 +++------- .../org/leavesmc/leaves/bot/agent/Actions.java | 16 ++++++++++++---- .../org/leavesmc/leaves/command/RootNode.java | 3 +++ .../org/leavesmc/leaves/entity/bot/CraftBot.java | 11 ++++++++--- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 9ad9406b..4ef591f1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -14,7 +14,6 @@ import org.bukkit.plugin.PluginManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.config.GlobalConfigManager; import org.leavesmc.leaves.config.annotations.GlobalConfig; import org.leavesmc.leaves.config.annotations.GlobalConfigCategory; @@ -136,17 +135,14 @@ public static class FakeplayerConfig { private static class FakeplayerValidator extends BooleanConfigValidator { @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { + if (old == null || old.equals(value)) { + return; + } if (value) { - Actions.registerAll(); BotCommand.INSTANCE.register(); } else { BotCommand.INSTANCE.unregister(); } - if (old != null && !old.equals(value)) { - Bukkit.getOnlinePlayers().stream() - .filter(BotCommand::hasPermission) - .forEach(org.bukkit.entity.Player::updateCommands); - } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index 9142fa14..7e0be5ea 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -16,7 +16,7 @@ public class Actions { private static final Map> actionsByName = new HashMap<>(); private static final Map, AbstractBotAction> actionsByClass = new HashMap<>(); - public static void registerAll() { + static { register(new ServerAttackAction(), AttackAction.class); register(new ServerBreakBlockAction(), BreakBlockAction.class); register(new ServerDropAction(), DropAction.class); @@ -38,7 +38,7 @@ public static void registerAll() { register(new ServerSwapAction(), SwapAction.class); } - public static boolean register(@NotNull AbstractBotAction action, Class> type) { + public static boolean register(@NotNull AbstractBotAction action, Class type) { if (!actionsByName.containsKey(action.getName())) { actionsByName.put(action.getName(), action); actionsByClass.put(type, action); @@ -47,9 +47,17 @@ public static boolean register(@NotNull AbstractBotAction action, Class action) { + return register(action, action.getClass()); + } + public static boolean unregister(@NotNull String name) { - // TODO add in custom action api - return true; + AbstractBotAction action = actionsByName.remove(name); + if (action != null) { + actionsByClass.remove(action.getClass()); + return true; + } + return false; } @NotNull diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java index 5066ce25..22d2b1e6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java @@ -5,6 +5,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -39,6 +40,7 @@ public void register() { .getCommands() .getDispatcher() .register((LiteralArgumentBuilder) compile()); + Bukkit.getOnlinePlayers().forEach(org.bukkit.entity.Player::updateCommands); } public void unregister() { @@ -46,5 +48,6 @@ public void unregister() { .getCommands() .getDispatcher(); dispatcher.getRoot().removeCommand(name); + Bukkit.getOnlinePlayers().forEach(org.bukkit.entity.Player::updateCommands); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java index 3ce7adac..6c3737ce 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java @@ -40,12 +40,17 @@ public String getSkinName() { @Override public > void addAction(@NotNull T action) { - switch (action) { - case CraftBotAction act -> this.getHandle().addBotAction(act.getHandle(), null); - default -> throw new IllegalArgumentException("Action " + action.getClass().getName() + " is not a valid BotAction type!"); + if (action instanceof CraftBotAction act) { + this.getHandle().addBotAction(act.getHandle(), null); + } else { + throw new IllegalArgumentException("Action " + action.getClass().getName() + " is not a valid BotAction type!"); } } + public void addAction(@NotNull AbstractBotAction action) { + this.getHandle().addBotAction(action, null); + } + @Override public BotAction getAction(int index) { return (BotAction) this.getHandle().getBotActions().get(index).asCraft(); From d0a41bb95773cd675996aa65e1b47cfae0037ffc Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Tue, 2 Sep 2025 11:43:43 +0800 Subject: [PATCH 19/29] feat: rename patch --- ...nfig-And-Command.patch => 0002-Leaves-Server-Config.patch} | 4 ++-- ...tion.patch => 0139-Modify-end-void-rings-generation.patch} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename leaves-server/minecraft-patches/features/{0002-Leaves-Server-Config-And-Command.patch => 0002-Leaves-Server-Config.patch} (87%) rename leaves-server/minecraft-patches/features/{0141-Modify-end-void-rings-generation.patch => 0139-Modify-end-void-rings-generation.patch} (100%) diff --git a/leaves-server/minecraft-patches/features/0002-Leaves-Server-Config-And-Command.patch b/leaves-server/minecraft-patches/features/0002-Leaves-Server-Config.patch similarity index 87% rename from leaves-server/minecraft-patches/features/0002-Leaves-Server-Config-And-Command.patch rename to leaves-server/minecraft-patches/features/0002-Leaves-Server-Config.patch index 160bc0af..29101d33 100644 --- a/leaves-server/minecraft-patches/features/0002-Leaves-Server-Config-And-Command.patch +++ b/leaves-server/minecraft-patches/features/0002-Leaves-Server-Config.patch @@ -1,11 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Sat, 1 Feb 2025 14:21:05 +0800 -Subject: [PATCH] Leaves Server Config And Command +Subject: [PATCH] Leaves Server Config diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index c22234df51a61954d1728b8406545f753dd8a3c2..d4775a33ee63a61e15ec3c1051261c01f2af28e0 100644 +index 461dc90ac9ae7f9af693653bc56a8cf448b7823e..414a8357a7498c69341fa634ada2e664e18ca03a 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java @@ -184,6 +184,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface diff --git a/leaves-server/minecraft-patches/features/0141-Modify-end-void-rings-generation.patch b/leaves-server/minecraft-patches/features/0139-Modify-end-void-rings-generation.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0141-Modify-end-void-rings-generation.patch rename to leaves-server/minecraft-patches/features/0139-Modify-end-void-rings-generation.patch From 63fdbf0770ee42dbb4d3ccd355325b629824dfd6 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Tue, 2 Sep 2025 21:27:14 +0800 Subject: [PATCH 20/29] fix: fix bot command register --- .../src/main/java/org/leavesmc/leaves/LeavesConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 42162b4d..3e300fad 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -135,7 +135,7 @@ public static class FakeplayerConfig { private static class FakeplayerValidator extends BooleanConfigValidator { @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { - if (old == null || old.equals(value)) { + if (value.equals(old)) { return; } if (value) { From 0bdc2db1168c975bfc24f1e5416d89ce4eed5def Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Thu, 11 Sep 2025 22:18:47 +0800 Subject: [PATCH 21/29] refactor: format & refactor code --- .../org/leavesmc/leaves/LeavesConfig.java | 61 +++++++++---------- .../bot/agent/actions/AbstractBotAction.java | 16 +++-- .../agent/actions/AbstractTimerBotAction.java | 4 +- .../agent/actions/AbstractUseBotAction.java | 4 +- .../bot/agent/actions/ServerLookAction.java | 10 --- .../bot/agent/actions/ServerMoveAction.java | 5 +- .../agent/actions/ServerRotationAction.java | 4 +- 7 files changed, 46 insertions(+), 58 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 3e300fad..061cbe08 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -14,6 +14,8 @@ import org.bukkit.plugin.PluginManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.bot.BotCommand; +import org.leavesmc.leaves.command.leaves.LeavesCommand; import org.leavesmc.leaves.config.GlobalConfigManager; import org.leavesmc.leaves.config.annotations.GlobalConfig; import org.leavesmc.leaves.config.annotations.GlobalConfigCategory; @@ -27,8 +29,6 @@ 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.command.bot.BotCommand; -import org.leavesmc.leaves.command.leaves.LeavesCommand; import org.leavesmc.leaves.profile.LeavesMinecraftSessionService; import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule; import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules; @@ -135,13 +135,12 @@ public static class FakeplayerConfig { private static class FakeplayerValidator extends BooleanConfigValidator { @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { - if (value.equals(old)) { - return; - } - if (value) { - BotCommand.INSTANCE.register(); - } else { - BotCommand.INSTANCE.unregister(); + if (!value.equals(old)) { + if (value) { + BotCommand.INSTANCE.register(); + } else { + BotCommand.INSTANCE.unregister(); + } } } } @@ -177,46 +176,46 @@ public void verify(Double old, Double value) throws IllegalArgumentException { @GlobalConfig("open-fakeplayer-inventory") public boolean canOpenInventory = false; - @GlobalConfig(value = "use-action", validator = CanUseActionValidator.class) + @GlobalConfig(value = "use-action", validator = CanUseConfigValidator.class) public boolean canUseAction = true; - 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 -> BotCommand.hasPermission(sender, "action")) - .forEach(org.bukkit.entity.Player::updateCommands); - } + private static class CanUseConfigValidator extends BotSubcommandValidator { + private CanUseConfigValidator() { + super("use"); } } @GlobalConfig(value = "modify-config", validator = CanModifyConfigValidator.class) public boolean canModifyConfig = false; - 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 -> - BotCommand.hasPermission(sender, "config") - ).forEach(org.bukkit.entity.Player::updateCommands); - } + private static class CanModifyConfigValidator extends BotSubcommandValidator { + private CanModifyConfigValidator() { + super("config"); } } @GlobalConfig(value = "manual-save-and-load", validator = CanManualSaveAndLoadValidator.class) public boolean canManualSaveAndLoad = false; - private static class CanManualSaveAndLoadValidator extends BooleanConfigValidator { + private static class CanManualSaveAndLoadValidator extends BotSubcommandValidator { + private CanManualSaveAndLoadValidator() { + super("save", "load"); + } + } + + private static class BotSubcommandValidator extends BooleanConfigValidator { + private final List subcommands; + + private BotSubcommandValidator(String... subcommand) { + this.subcommands = List.of(subcommand); + } + @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { if (old != null && !old.equals(value)) { Bukkit.getOnlinePlayers().stream() - .filter(sender -> - BotCommand.hasPermission(sender, "save") || BotCommand.hasPermission(sender, "load") - ).forEach(org.bukkit.entity.Player::updateCommands); + .filter(sender -> subcommands.stream().allMatch(subcommand -> BotCommand.hasPermission(sender, subcommand))) + .forEach(org.bukkit.entity.Player::updateCommands); } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index eb798ee2..bf82942c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -6,12 +6,13 @@ import net.minecraft.nbt.CompoundTag; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; -import org.leavesmc.leaves.event.bot.BotActionStopEvent; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.WrappedArgument; +import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; +import org.leavesmc.leaves.event.bot.BotActionStopEvent; import org.leavesmc.leaves.util.UpdateSuppressionException; import java.util.ArrayList; @@ -59,12 +60,11 @@ public AbstractBotAction(String name, Supplier creator) { public abstract Object asCraft(); - public void provideActionData(@NotNull ActionData data) { + public String getActionDataString() { + return getActionDataString(new ActionData(new ArrayList<>())); } - public String getActionDataString() { - ActionData data = new ActionData(new ArrayList<>()); - provideActionData(data); + public String getActionDataString(@NotNull ActionData data) { return data.raw.stream() .map(pair -> pair.getLeft() + "=" + pair.getRight()) .reduce((a, b) -> a + ", " + b) @@ -249,9 +249,7 @@ public void setOnStop(Consumer onStop) { this.onStop = onStop; } - public record ActionData( - List> raw - ) { + public record ActionData(List> raw) { public void add(String key, String value) { raw.add(Pair.of(key, value)); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index 15d904ce..748398d2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -32,11 +32,11 @@ public void loadCommand(@NotNull CommandContext context) { } @Override - public void provideActionData(@NotNull ActionData data) { - super.provideActionData(data); + public String getActionDataString(@NotNull ActionData data) { data.add("delay", String.valueOf(this.getStartDelayTick())); data.add("interval", String.valueOf(this.getDoIntervalTick())); data.add("do_number", String.valueOf(this.getDoNumber())); data.add("remaining_do_number", String.valueOf(this.getDoNumberRemaining())); + return super.getActionDataString(data); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 69b8fd9f..4cf4c3f1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -98,10 +98,10 @@ private void increaseAlreadyUsedTick() { } @Override - public void provideActionData(@NotNull ActionData data) { - super.provideActionData(data); + public String getActionDataString(@NotNull ActionData data) { data.add("use_timeout", String.valueOf(this.useTickTimeout)); data.add("already_used_tick", String.valueOf(this.alreadyUsedTick)); + return super.getActionDataString(data); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index bbf11568..2aba85f8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -98,16 +98,6 @@ public ServerPlayer getTarget() { return target; } - @Override - public void provideActionData(@NotNull ActionData data) { - super.provideActionData(data); - if (target != null) { - data.add("target", target.getName().getString()); - } else { - data.add("position", String.format("(%.2f, %.2f, %.2f)", pos.getX(), pos.getY(), pos.getZ())); - } - } - @Override public boolean doTick(@NotNull ServerBot bot) { if (target != null) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 3d3db621..b9a639d5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -3,6 +3,7 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; @@ -65,9 +66,9 @@ public boolean doTick(@NotNull ServerBot bot) { } @Override - public void provideActionData(@NotNull ActionData data) { - super.provideActionData(data); + public String getActionDataString(@NotNull ActionData data) { data.add("direction", direction.name); + return super.getActionDataString(data); } public MoveDirection getDirection() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 86f9fdaf..b7c6dbd0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -57,10 +57,10 @@ public float getPitch() { } @Override - public void provideActionData(@NotNull ActionData data) { - super.provideActionData(data); + public String getActionDataString(@NotNull ActionData data) { data.add("yaw", DF.format(this.yaw)); data.add("pitch", DF.format(this.pitch)); + return super.getActionDataString(data); } @Override From dd3af554954df223cf9a7643e24e7c7a7d4949c1 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Tue, 23 Sep 2025 16:21:47 +0800 Subject: [PATCH 22/29] Some format --- ...mand.patch => 0003-Leaves-Server-Config.patch} | 4 ++-- .../org/leavesmc/leaves/bot/agent/Actions.java | 2 +- .../bot/agent/actions/AbstractBotAction.java | 1 - .../bot/agent/actions/AbstractStateBotAction.java | 1 - .../bot/agent/actions/AbstractTimerBotAction.java | 8 ++------ .../bot/agent/actions/AbstractUseBotAction.java | 2 +- .../bot/agent/actions/ServerLookAction.java | 14 ++------------ .../bot/agent/actions/ServerMoveAction.java | 9 ++------- .../bot/agent/actions/ServerRotationAction.java | 2 +- .../org/leavesmc/leaves/command/CommandUtils.java | 6 +----- .../leaves/command/CustomArgumentType.java | 1 - .../leaves/command/bot/BotSubcommand.java | 1 - .../command/bot/subcommands/ConfigCommand.java | 7 ++----- .../command/bot/subcommands/CreateCommand.java | 6 +----- .../command/bot/subcommands/LoadCommand.java | 6 +----- .../command/bot/subcommands/RemoveCommand.java | 15 ++++++++++----- .../command/bot/subcommands/SaveCommand.java | 2 +- .../bot/subcommands/action/ListCommand.java | 5 +---- .../bot/subcommands/action/StartCommand.java | 5 +---- .../bot/subcommands/action/StopCommand.java | 2 +- .../leaves/command/leaves/LeavesCommand.java | 1 + .../leaves/subcommands/BlockUpdateCommand.java | 2 -- .../command/leaves/subcommands/ConfigCommand.java | 13 +++++-------- .../leaves/subcommands/CounterCommand.java | 5 ----- .../command/leaves/subcommands/ReloadCommand.java | 1 - .../litematics/ServuxLitematicsProtocol.java | 2 +- .../leavesmc/leaves/util/ShearsWrenchUtil.java | 2 -- 27 files changed, 37 insertions(+), 88 deletions(-) rename leaves-server/paper-patches/features/{0003-Leaves-Server-Config-And-Command.patch => 0003-Leaves-Server-Config.patch} (95%) diff --git a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch b/leaves-server/paper-patches/features/0003-Leaves-Server-Config.patch similarity index 95% rename from leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch rename to leaves-server/paper-patches/features/0003-Leaves-Server-Config.patch index 0bd858fc..6b05bd9e 100644 --- a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch +++ b/leaves-server/paper-patches/features/0003-Leaves-Server-Config.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Sat, 1 Feb 2025 14:21:06 +0800 -Subject: [PATCH] Leaves Server Config And Command +Subject: [PATCH] Leaves Server Config diff --git a/src/main/java/io/papermc/paper/SparksFly.java b/src/main/java/io/papermc/paper/SparksFly.java @@ -18,7 +18,7 @@ index 62e2d5704c348955bc8284dc2d54c933b7bcdd06..7ef20f0138fad39a1d23edd7b26ddc88 public void executeAsync(final Runnable runnable) { MCUtil.scheduleAsyncTask(this.catching(runnable, "asynchronous")); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 32fe51b19323e3c4c56e7f9e621e6e808ee5fe38..2eba1d900b20a781c4bb08caa2b30bfeb2d02b9d 100644 +index 1d12a870a2f239bf95df639ef350b38911558199..1e9a43814613b57483845cc4f66b9be4717b746f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1076,6 +1076,7 @@ public final class CraftServer implements Server { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index 7e0be5ea..214165eb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -16,7 +16,7 @@ public class Actions { private static final Map> actionsByName = new HashMap<>(); private static final Map, AbstractBotAction> actionsByClass = new HashMap<>(); - static { + static { register(new ServerAttackAction(), AttackAction.class); register(new ServerBreakBlockAction(), BreakBlockAction.class); register(new ServerDropAction(), DropAction.class); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index bf82942c..af98d6e4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -6,7 +6,6 @@ import net.minecraft.nbt.CompoundTag; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.CommandContext; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java index 6a6007fc..75876ab8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java @@ -3,7 +3,6 @@ import java.util.function.Supplier; public abstract class AbstractStateBotAction> extends AbstractBotAction { - public AbstractStateBotAction(String name, Supplier creator) { super(name, creator); this.setDoNumber(-1); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index 748398d2..632a08bf 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -13,12 +13,8 @@ public abstract class AbstractTimerBotAction public AbstractTimerBotAction(String name, Supplier creator) { super(name, creator); - this.addArgument("delay", integer(0)) - .suggests(strings("0", "5", "10", "20")) - .setOptional(true); - this.addArgument("interval", integer(0)) - .suggests(strings("20", "0", "5", "10")) - .setOptional(true); + this.addArgument("delay", integer(0)).suggests(strings("0", "5", "10", "20")).setOptional(true); + this.addArgument("interval", integer(0)).suggests(strings("20", "0", "5", "10")).setOptional(true); this.addArgument("do_number", integer(-1)) .suggests(((context, builder) -> builder.suggest("-1", Component.literal("do infinite times")))) .setOptional(true); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 4cf4c3f1..787cec99 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -5,8 +5,8 @@ import net.minecraft.world.InteractionResult; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.event.bot.BotActionStopEvent; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.event.bot.BotActionStopEvent; import java.util.function.Supplier; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index 2aba85f8..a003bd51 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -13,8 +13,8 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; public class ServerLookAction extends AbstractBotAction { @@ -25,17 +25,7 @@ public class ServerLookAction extends AbstractBotAction { public ServerLookAction() { super("look", ServerLookAction::new); - declarePlayerBranch(); - declareLocationBranch(); - } - - private void declarePlayerBranch() { - this.fork(0); - this.addArgument("player", EntityArgument.player()) - .setOptional(true); - } - - private void declareLocationBranch() { + this.addArgument("player", EntityArgument.player()).setOptional(true); this.fork(1); this.addArgument("location", Vec3Argument.vec3(false)); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index b9a639d5..d7de3f57 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -3,12 +3,11 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import org.leavesmc.leaves.command.CommandContext; import java.util.Arrays; import java.util.Map; @@ -26,11 +25,7 @@ public class ServerMoveAction extends AbstractStateBotAction { public ServerMoveAction() { super("move", ServerMoveAction::new); this.addArgument("direction", StringArgumentType.word()) - .suggests(strings( - Arrays.stream(MoveDirection.values()) - .map((it) -> it.name) - .toList() - )); + .suggests(strings(Arrays.stream(MoveDirection.values()).map((it) -> it.name).toList())); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index b7c6dbd0..55af45a1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -6,8 +6,8 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; import java.text.DecimalFormat; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java index 8c518f74..a270312f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java @@ -40,10 +40,7 @@ public static void registerPermissions(@NotNull List permissions) { } @DefaultQualifier(NonNull.class) - public static @NotNull List getListClosestMatchingLast( - final String last, - final Collection collection - ) { + public static @NotNull List getListClosestMatchingLast(final String last, final Collection collection) { if (collection.isEmpty()) { return Collections.emptyList(); } @@ -132,7 +129,6 @@ private static int damerauLevenshteinDistance(@Nullable String s1, @Nullable Str 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) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java index 3e44ede1..86d3c5f6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java @@ -8,7 +8,6 @@ import java.util.concurrent.CompletableFuture; public interface CustomArgumentType { - ArgumentType getBaseArgumentType(); T transform(B value) throws CommandSyntaxException; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java index f6d215eb..0adae7a1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java @@ -5,7 +5,6 @@ import org.leavesmc.leaves.command.LiteralNode; public abstract class BotSubcommand extends LiteralNode { - protected BotSubcommand(String name) { super(name); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java index b28f9cd4..10dc2e56 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java @@ -42,9 +42,7 @@ private static class BotArgument extends CustomArgumentNode { private BotArgument() { super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); - Configs.getConfigs().stream() - .map(this::configNodeCreator) - .forEach(this::children); + Configs.getConfigs().stream().map(this::configNodeCreator).forEach(this::children); } @Contract(pure = true) @@ -93,8 +91,7 @@ private ConfigNode(@NotNull AbstractBotConfig config) { CommandContext ctx = new CommandContext(mojangCtx); return executeSet(ctx) ? 1 : 0; }); - return super.compileBase() - .then(argument); + return super.compileBase().then(argument); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index 2812ff18..df406a58 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -19,10 +19,10 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.BotCreateState; import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.event.bot.BotCreateEvent; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.event.bot.BotCreateEvent; import static net.kyori.adventure.text.Component.text; import static net.minecraft.commands.arguments.DimensionArgument.getDimension; @@ -99,7 +99,6 @@ private static boolean canCreate(CommandSender sender, @NotNull String name) { } private static class NameArgument extends ArgumentNode { - private NameArgument() { super("name", StringArgumentType.word()); children(SkinNameArgument::new); @@ -112,7 +111,6 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException } private static class SkinNameArgument extends ArgumentNode { - private SkinNameArgument() { super("skin_name", StringArgumentType.word()); children(WorldArgument::new); @@ -125,7 +123,6 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException } private static class WorldArgument extends ArgumentNode { - private WorldArgument() { super("world", DimensionArgument.dimension()); children(LocationArgument::new); @@ -138,7 +135,6 @@ public boolean requires(@NotNull CommandSourceStack source) { } private static class LocationArgument extends ArgumentNode { - private LocationArgument() { super("location", Vec3Argument.vec3(true)); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java index 2ef59a4b..699848f6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -55,11 +55,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE 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()) - )); + sender.sendMessage(join(spaces(), text("Successfully loaded bot", NamedTextColor.GRAY), asAdventure(bot.getDisplayName()))); return true; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java index 0b154961..09df5362 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -9,11 +9,11 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.event.bot.BotRemoveEvent; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.CustomArgumentNode; import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.event.bot.BotRemoveEvent; import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; import java.util.regex.Matcher; @@ -42,7 +42,6 @@ private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender } private static class BotArgument extends CustomArgumentNode { - private BotArgument() { super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); children(RemoveTimeArgument::new); @@ -116,9 +115,15 @@ private static int parseRemoveTime(String timeStr) throws CommandSyntaxException foundMatch = true; int value = Integer.parseInt(matcher.group(1)); switch (matcher.group(2).toLowerCase()) { - case "h": seconds += value * 3600; break; - case "m": seconds += value * 60; break; - case "s": seconds += value; break; + case "h": + seconds += value * 3600; + break; + case "m": + seconds += value * 60; + break; + case "s": + seconds += value; + break; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java index 28b69dd8..218c06da 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -8,10 +8,10 @@ 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.command.CommandContext; import org.leavesmc.leaves.command.CustomArgumentNode; import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.event.bot.BotRemoveEvent; import static io.papermc.paper.adventure.PaperAdventure.asAdventure; import static net.kyori.adventure.text.Component.join; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java index 2d39b36c..1547891e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java @@ -36,10 +36,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE return true; } - sender.sendMessage( - asAdventure(bot.getDisplayName()) - .append(text("'s action list:", GRAY)) - ); + sender.sendMessage(asAdventure(bot.getDisplayName()).append(text("'s action list:", GRAY))); for (int i = 0; i < actions.size(); i++) { AbstractBotAction action = actions.get(i); sender.sendMessage(join(spaces(), diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java index 23159cba..8a7b0a18 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -32,10 +32,7 @@ public class StartCommand extends LiteralNode { public StartCommand() { super("start"); - Actions.getAll() - .stream() - .map(this::actionNodeCreator) - .forEach(this::children); + Actions.getAll().stream().map(this::actionNodeCreator).forEach(this::children); } private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotAction action) throws CommandSyntaxException { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java index d92493de..16d75583 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java @@ -9,11 +9,11 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; -import org.leavesmc.leaves.event.bot.BotActionStopEvent; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; +import org.leavesmc.leaves.event.bot.BotActionStopEvent; import java.util.HashSet; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java index e3ee08b6..f30ec31d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java @@ -11,6 +11,7 @@ import org.leavesmc.leaves.command.leaves.subcommands.UpdateCommand; public class LeavesCommand extends RootNode { + public static final LeavesCommand INSTANCE = new LeavesCommand(); private static final String PERM_BASE = "bukkit.command.leaves"; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java index f9d5e841..9c91bb93 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java @@ -46,7 +46,6 @@ public boolean requires(@NotNull CommandSourceStack source) { } private class EnableNode extends LiteralNode { - private EnableNode() { super("enable"); } @@ -73,7 +72,6 @@ protected boolean execute(@NotNull CommandContext context) { } private class DisableNode extends LiteralNode { - private DisableNode() { super("disable"); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java index 8dddd120..5d32cbc4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -6,11 +6,12 @@ import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.config.GlobalConfigManager; -import org.leavesmc.leaves.config.VerifiedConfig; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CommandUtils; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; +import org.leavesmc.leaves.config.GlobalConfigManager; +import org.leavesmc.leaves.config.VerifiedConfig; import java.util.concurrent.CompletableFuture; @@ -18,7 +19,6 @@ 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.command.CommandUtils.getListClosestMatchingLast; public class ConfigCommand extends LeavesSubcommand { @@ -39,10 +39,8 @@ protected CompletableFuture getSuggestions(@NotNull CommandContext String path = context.getArgumentOrDefault(PathArgument.class, ""); int dotIndex = path.lastIndexOf("."); builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2); - getListClosestMatchingLast( - path.substring(dotIndex + 1), - GlobalConfigManager.getVerifiedConfigSubPaths(path) - ).forEach(builder::suggest); + CommandUtils.getListClosestMatchingLast(path.substring(dotIndex + 1), GlobalConfigManager.getVerifiedConfigSubPaths(path)) + .forEach(builder::suggest); return builder.buildFuture(); } @@ -75,7 +73,6 @@ protected boolean execute(@NotNull CommandContext context) { } return verifiedConfig; } - } private static class ValueArgument extends ArgumentNode { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java index d9e74f29..4329415d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java @@ -48,7 +48,6 @@ protected boolean execute(@NotNull CommandContext context) { } private static class EnableNode extends LiteralNode { - private EnableNode() { super("enable"); } @@ -73,7 +72,6 @@ protected boolean execute(@NotNull CommandContext context) { } private static class DisableNode extends LiteralNode { - private DisableNode() { super("disable"); } @@ -98,7 +96,6 @@ protected boolean execute(@NotNull CommandContext context) { } private static class ResetAllNode extends LiteralNode { - private ResetAllNode() { super("reset"); } @@ -138,7 +135,6 @@ private void displayCounter(CommandSender sender, boolean realTime) { } private class ResetNode extends LiteralNode { - private ResetNode() { super("reset"); } @@ -155,7 +151,6 @@ protected boolean execute(@NotNull CommandContext context) { } private class RealtimeNode extends LiteralNode { - private RealtimeNode() { super("realtime"); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java index 72be57c2..bf4d4428 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java @@ -12,7 +12,6 @@ import static net.kyori.adventure.text.format.NamedTextColor.GREEN; public class ReloadCommand extends LeavesSubcommand { - public ReloadCommand() { super("reload"); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java index 7f744bab..925a0e96 100755 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java @@ -104,7 +104,7 @@ public static void onPacketReceive(ServerPlayer player, ServuxLitematicaPayload case PACKET_C2S_BLOCK_ENTITY_REQUEST -> onBlockEntityRequest(player, payload.getPos()); case PACKET_C2S_ENTITY_REQUEST -> onEntityRequest(player, payload.getEntityId()); - + case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> onBulkEntityRequest(player, payload.getChunkPos(), payload.getCompound()); case PACKET_C2S_NBT_RESPONSE_DATA -> { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java index 07fb9a13..217d6ceb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java @@ -7,8 +7,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.*; From 9fefded7e254e7b8cf71b943ae2dee4846f0330c Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Tue, 23 Sep 2025 18:45:52 +0800 Subject: [PATCH 23/29] refactor: refactor config and action --- .../leavesmc/leaves/bot/agent/ExtraData.java | 11 ++++++ .../bot/agent/actions/AbstractBotAction.java | 13 +++---- .../agent/actions/AbstractTimerBotAction.java | 3 +- .../agent/actions/AbstractUseBotAction.java | 3 +- .../bot/agent/actions/ServerMoveAction.java | 3 +- .../agent/actions/ServerRotationAction.java | 3 +- .../bot/agent/configs/AbstractBotConfig.java | 36 +++++++++---------- .../bot/agent/configs/SpawnPhantomConfig.java | 9 +++-- 8 files changed, 43 insertions(+), 38 deletions(-) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java new file mode 100644 index 00000000..46c852ab --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java @@ -0,0 +1,11 @@ +package org.leavesmc.leaves.bot.agent; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +public record ExtraData(List> raw) { + public void add(String key, String value) { + raw.add(Pair.of(key, value)); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index af98d6e4..b59b0be5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.WrappedArgument; import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; @@ -60,11 +61,11 @@ public AbstractBotAction(String name, Supplier creator) { public abstract Object asCraft(); public String getActionDataString() { - return getActionDataString(new ActionData(new ArrayList<>())); + return getActionDataString(new ExtraData(new ArrayList<>())); } - public String getActionDataString(@NotNull ActionData data) { - return data.raw.stream() + public String getActionDataString(@NotNull ExtraData data) { + return data.raw().stream() .map(pair -> pair.getLeft() + "=" + pair.getRight()) .reduce((a, b) -> a + ", " + b) .orElse("No arguments"); @@ -247,10 +248,4 @@ public void setOnSuccess(Consumer onSuccess) { public void setOnStop(Consumer onStop) { this.onStop = onStop; } - - public record ActionData(List> raw) { - public void add(String key, String value) { - raw.add(Pair.of(key, value)); - } - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index 632a08bf..817b5ec0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -2,6 +2,7 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; import java.util.function.Supplier; @@ -28,7 +29,7 @@ public void loadCommand(@NotNull CommandContext context) { } @Override - public String getActionDataString(@NotNull ActionData data) { + public String getActionDataString(@NotNull ExtraData data) { data.add("delay", String.valueOf(this.getStartDelayTick())); data.add("interval", String.valueOf(this.getDoIntervalTick())); data.add("do_number", String.valueOf(this.getDoNumber())); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 787cec99..2d2fa41b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -5,6 +5,7 @@ import net.minecraft.world.InteractionResult; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.event.bot.BotActionStopEvent; @@ -98,7 +99,7 @@ private void increaseAlreadyUsedTick() { } @Override - public String getActionDataString(@NotNull ActionData data) { + public String getActionDataString(@NotNull ExtraData data) { data.add("use_timeout", String.valueOf(this.useTickTimeout)); data.add("already_used_tick", String.valueOf(this.alreadyUsedTick)); return super.getActionDataString(data); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index d7de3f57..8da91cff 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; @@ -61,7 +62,7 @@ public boolean doTick(@NotNull ServerBot bot) { } @Override - public String getActionDataString(@NotNull ActionData data) { + public String getActionDataString(@NotNull ExtraData data) { data.add("direction", direction.name); return super.getActionDataString(data); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 55af45a1..04dc0d6f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -6,6 +6,7 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; @@ -57,7 +58,7 @@ public float getPitch() { } @Override - public String getActionDataString(@NotNull ActionData data) { + public String getActionDataString(@NotNull ExtraData data) { data.add("yaw", DF.format(this.yaw)); data.add("pitch", DF.format(this.pitch)); return super.getActionDataString(data); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java index 16a6e5b7..b5b58e41 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -4,21 +4,19 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.nbt.CompoundTag; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.WrappedArgument; import java.lang.reflect.Method; -import java.util.List; +import java.util.ArrayList; import java.util.function.Supplier; -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.event.HoverEvent.showText; -import static net.kyori.adventure.text.format.NamedTextColor.AQUA; - public abstract class AbstractBotConfig> { private final String name; private final WrappedArgument argument; @@ -54,25 +52,23 @@ public E create() { public abstract Value loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; - public List> getExtraData() { - return List.of(); - } - public String getName() { return name; } public Component getNameComponent() { - Component result = text(getName(), AQUA); - if (!getExtraData().isEmpty()) { - result = result.hoverEvent(showText( - getExtraData().stream() - .map(pair -> text(pair.getKey() + "=" + pair.getValue())) - .reduce((a, b) -> a.append(text(", ")).append(b)) - .orElseGet(() -> text("")) - )); - } - return result; + return Component.text(getName(), NamedTextColor.AQUA).hoverEvent(HoverEvent.showText(Component.text(getExtraDataString()))); + } + + public String getExtraDataString() { + return getExtraDataString(new ExtraData(new ArrayList<>())); + } + + public String getExtraDataString(@NotNull ExtraData data) { + return data.raw().stream() + .map(pair -> pair.getLeft() + "=" + pair.getRight()) + .reduce((a, b) -> a + ", " + b) + .orElse("No data"); } public WrappedArgument getArgument() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index 25ec048f..49257361 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -2,13 +2,11 @@ import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; -import java.util.List; - public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; @@ -28,8 +26,9 @@ public void setValue(Boolean value) throws IllegalArgumentException { } @Override - public List> getExtraData() { - return List.of(Pair.of("not_sleeping_ticks", String.valueOf(bot.notSleepTicks))); + public String getExtraDataString(@NotNull ExtraData data) { + data.add("not_sleeping_ticks", String.valueOf(bot.notSleepTicks)); + return super.getExtraDataString(data); } @Override From e5d5c4714e3dc8e0370b2e452bcbae312ba40165 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Wed, 24 Sep 2025 13:07:28 +0800 Subject: [PATCH 24/29] refactor: use paper command api --- .../org/leavesmc/leaves/bot/ServerBot.java | 18 ++--- .../leavesmc/leaves/bot/agent/Configs.java | 8 +- .../bot/agent/actions/ServerLookAction.java | 41 +++++----- .../bot/agent/actions/ServerMoveAction.java | 25 +----- .../agent/actions/ServerRotationAction.java | 40 ++++++--- .../bot/agent/configs/AbstractBotConfig.java | 16 ++-- .../agent/configs/AlwaysSendDataConfig.java | 2 +- .../bot/agent/configs/LocatorBarConfig.java | 2 +- .../configs/SimulationDistanceConfig.java | 2 +- .../bot/agent/configs/SkipSleepConfig.java | 2 +- .../bot/agent/configs/SpawnPhantomConfig.java | 2 +- .../bot/agent/configs/TickTypeConfig.java | 23 ++---- .../leavesmc/leaves/command/ArgumentNode.java | 4 +- .../leaves/command/CommandContext.java | 18 +---- .../leavesmc/leaves/command/CommandNode.java | 2 +- .../leavesmc/leaves/command/CommandUtils.java | 2 +- .../leaves/command/CustomArgumentNode.java | 44 ---------- .../leaves/command/CustomArgumentType.java | 16 ---- .../leavesmc/leaves/command/LiteralNode.java | 4 +- .../org/leavesmc/leaves/command/RootNode.java | 19 ++--- .../leaves/command/WrappedArgument.java | 4 +- .../BotArgumentType.java} | 37 ++++----- .../command/arguments/EnumArgumentType.java | 81 +++++++++++++++++++ .../leaves/command/bot/BotCommand.java | 2 +- .../leaves/command/bot/BotSubcommand.java | 2 +- .../bot/subcommands/ActionCommand.java | 14 ++-- .../bot/subcommands/ConfigCommand.java | 33 ++++---- .../bot/subcommands/CreateCommand.java | 29 +++---- .../command/bot/subcommands/ListCommand.java | 16 ++-- .../command/bot/subcommands/LoadCommand.java | 2 +- .../bot/subcommands/RemoveCommand.java | 12 +-- .../command/bot/subcommands/SaveCommand.java | 14 ++-- .../bot/subcommands/action/StartCommand.java | 2 +- .../command/leaves/LeavesSubcommand.java | 2 +- .../subcommands/BlockUpdateCommand.java | 2 +- .../leaves/subcommands/ConfigCommand.java | 2 +- .../leaves/subcommands/CounterCommand.java | 2 +- 37 files changed, 266 insertions(+), 280 deletions(-) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java rename leaves-server/src/main/java/org/leavesmc/leaves/command/{bot/BotArgument.java => arguments/BotArgumentType.java} (62%) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java index 3a50a140..f000526c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java @@ -84,7 +84,7 @@ public class ServerBot extends ServerPlayer { private final List> actions; - private final Map> configs; + private final Map> configs; public boolean resume = false; public BotCreateState createState; @@ -106,8 +106,8 @@ public ServerBot(MinecraftServer server, ServerLevel world, GameProfile profile) this.gameMode = new ServerBotGameMode(this); this.actions = new ArrayList<>(); - ImmutableMap.Builder> configBuilder = ImmutableMap.builder(); - for (AbstractBotConfig config : Configs.getConfigs()) { + ImmutableMap.Builder> configBuilder = ImmutableMap.builder(); + for (AbstractBotConfig config : Configs.getConfigs()) { configBuilder.put(config.getName(), config.create().setBot(this)); } this.configs = configBuilder.build(); @@ -395,7 +395,7 @@ public void addAdditionalSaveData(@NotNull ValueOutput nbt) { if (!this.configs.isEmpty()) { ValueOutput.TypedOutputList configNbt = nbt.list("configs", CompoundTag.CODEC); - for (AbstractBotConfig config : this.configs.values()) { + for (AbstractBotConfig config : this.configs.values()) { configNbt.add(config.save(new CompoundTag())); } } @@ -440,7 +440,7 @@ public void readAdditionalSaveData(@NotNull ValueInput nbt) { if (nbt.list("configs", CompoundTag.CODEC).isPresent()) { ValueInput.TypedInputList configNbt = nbt.list("configs", CompoundTag.CODEC).orElseThrow(); for (CompoundTag configTag : configNbt) { - AbstractBotConfig config = Configs.getConfig(configTag.getString("configName").orElseThrow()); + AbstractBotConfig config = Configs.getConfig(configTag.getString("configName").orElseThrow()); if (config != null) { config.load(configTag); } @@ -669,15 +669,15 @@ public ServerStatsCounter getStats() { } @SuppressWarnings("unchecked") - public > AbstractBotConfig getConfig(@NotNull AbstractBotConfig config) { - return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config.getName())); + public > AbstractBotConfig getConfig(@NotNull AbstractBotConfig config) { + return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config.getName())); } - public Collection> getAllConfigs() { + public Collection> getAllConfigs() { return configs.values(); } - public > O getConfigValue(@NotNull AbstractBotConfig config) { + public > T getConfigValue(@NotNull AbstractBotConfig config) { return this.getConfig(config).getValue(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java index 056c1cbf..602aff02 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java @@ -17,7 +17,7 @@ @SuppressWarnings({"unused"}) public class Configs { - private static final Map, AbstractBotConfig> configs = new HashMap<>(); + private static final Map, AbstractBotConfig> configs = new HashMap<>(); public static final SkipSleepConfig SKIP_SLEEP = register(new SkipSleepConfig()); public static final AlwaysSendDataConfig ALWAYS_SEND_DATA = register(new AlwaysSendDataConfig()); @@ -27,7 +27,7 @@ public class Configs { public static final LocatorBarConfig ENABLE_LOCATOR_BAR = register(new LocatorBarConfig()); @Nullable - public static AbstractBotConfig getConfig(String name) { + public static AbstractBotConfig getConfig(String name) { return configs.values().stream() .filter(config -> config.getName().equals(name)) .findFirst() @@ -36,12 +36,12 @@ public class Configs { @NotNull @Contract(pure = true) - public static Collection> getConfigs() { + public static Collection> getConfigs() { return configs.values(); } @SuppressWarnings("unchecked") - private static > @NotNull E register(AbstractBotConfig instance) { + private static > @NotNull E register(AbstractBotConfig instance) { configs.put(instance.getClass(), instance); return (E) instance; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index a003bd51..8333826d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -1,15 +1,15 @@ package org.leavesmc.leaves.bot.agent.actions; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.commands.arguments.coordinates.Coordinates; -import net.minecraft.commands.arguments.coordinates.Vec3Argument; -import net.minecraft.commands.arguments.selector.EntitySelector; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; +import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; +import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Entity; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; @@ -25,25 +25,28 @@ public class ServerLookAction extends AbstractBotAction { public ServerLookAction() { super("look", ServerLookAction::new); - this.addArgument("player", EntityArgument.player()).setOptional(true); + this.addArgument("player", ArgumentTypes.player()).setOptional(true); this.fork(1); - this.addArgument("location", Vec3Argument.vec3(false)); + this.addArgument("location", ArgumentTypes.finePosition()); } @Override public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { - EntitySelector selector = context.getArgumentOrDefault("player", EntitySelector.class, null); - Coordinates location = context.getArgumentOrDefault("location", Coordinates.class, null); + PlayerSelectorArgumentResolver playerSelectorResolver = context.getArgumentOrDefault("player", PlayerSelectorArgumentResolver.class, null); + FinePositionResolver positionResolver = context.getArgumentOrDefault("location", FinePositionResolver.class, null); CommandSourceStack source = context.getSource(); - if (selector == null && location == null) { - Entity sender = source.getEntityOrException(); - this.setPos(new Vector(sender.getX(), sender.getY(), sender.getZ())); - } else if (selector != null) { - ServerPlayer player = selector.findSinglePlayer(source); - this.setTarget(player); + if (playerSelectorResolver == null && positionResolver == null) { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + this.setPos(entity.getLocation().toVector()); + } else { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().create(); + } + } else if (playerSelectorResolver != null) { + CraftPlayer player = (CraftPlayer) playerSelectorResolver.resolve(source).getFirst(); + this.setTarget(player.getHandle()); } else { - Vec3 vector = location.getPosition(source); - this.setPos(new Vector(vector.x, vector.y, vector.z)); + this.setPos(positionResolver.resolve(source).toVector()); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 8da91cff..4023b469 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -1,42 +1,25 @@ package org.leavesmc.leaves.bot.agent.actions; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.EnumArgumentType; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import java.util.Arrays; -import java.util.Map; - -import static java.util.stream.Collectors.toMap; -import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings; - public class ServerMoveAction extends AbstractStateBotAction { - private static final Map NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap( - it -> it.name, - it -> it - )); private MoveDirection direction = MoveDirection.FORWARD; public ServerMoveAction() { super("move", ServerMoveAction::new); - this.addArgument("direction", StringArgumentType.word()) - .suggests(strings(Arrays.stream(MoveDirection.values()).map((it) -> it.name).toList())); + this.addArgument("direction", EnumArgumentType.fromEnum(MoveDirection.class)); } @Override - public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { - String raw = context.getArgument("direction", String.class); - MoveDirection direction = NAME_TO_DIRECTION.get(raw); - if (direction == null) { - throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); - } - this.direction = direction; + public void loadCommand(@NotNull CommandContext context) { + this.direction = context.getArgument("direction", MoveDirection.class); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 04dc0d6f..85f51064 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -1,9 +1,10 @@ package org.leavesmc.leaves.bot.agent.actions; import com.mojang.brigadier.arguments.FloatArgumentType; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.ExtraData; @@ -19,16 +20,26 @@ public class ServerRotationAction extends AbstractBotAction builder.suggest( - DF.format(context.getSource().getEntityOrException().getYRot()), - Component.literal("current player yaw") - )) + .suggests((context, builder) -> { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + builder.suggest( + DF.format(entity.getYaw()), + Component.literal("current player yaw") + ); + } + }) .setOptional(true); this.addArgument("pitch", FloatArgumentType.floatArg(-90, 90)) - .suggests((context, builder) -> builder.suggest( - DF.format(context.getSource().getEntityOrException().getXRot()), - Component.literal("current player pitch") - )) + .suggests((context, builder) -> { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + builder.suggest( + DF.format(entity.getPitch()), + Component.literal("current player pitch") + ); + } + }) .setOptional(true); } @@ -36,9 +47,14 @@ public ServerRotationAction() { private float pitch = 0.0f; @Override - public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { - this.yaw = context.getFloatOrDefault("yaw", context.getSource().getEntityOrException().getYRot()); - this.pitch = context.getFloatOrDefault("pitch", context.getSource().getEntityOrException().getXRot()); + public void loadCommand(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + this.yaw = entity.getYaw(); + this.pitch = entity.getPitch(); + } + this.yaw = context.getFloatOrDefault("yaw", this.yaw); + this.pitch = context.getFloatOrDefault("pitch", this.pitch); } public void setYaw(float yaw) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java index b5b58e41..7b87332d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -17,14 +17,14 @@ import java.util.ArrayList; import java.util.function.Supplier; -public abstract class AbstractBotConfig> { +public abstract class AbstractBotConfig> { private final String name; - private final WrappedArgument argument; + private final WrappedArgument argument; private final Supplier creator; protected ServerBot bot; - public AbstractBotConfig(String name, ArgumentType type, Supplier creator) { + public AbstractBotConfig(String name, ArgumentType type, Supplier creator) { this.name = name; this.argument = new WrappedArgument<>(name, type); if (shouldApplySuggestions()) { @@ -37,7 +37,7 @@ public AbstractBotConfig(String name, ArgumentType type, Supplier creat public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { } - public AbstractBotConfig setBot(ServerBot bot) { + public AbstractBotConfig setBot(ServerBot bot) { this.bot = bot; return this; } @@ -46,11 +46,11 @@ public E create() { return creator.get(); } - public abstract Value getValue(); + public abstract T getValue(); - public abstract void setValue(Value value) throws CommandSyntaxException; + public abstract void setValue(T value) throws CommandSyntaxException; - public abstract Value loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; + public abstract T loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; public String getName() { return name; @@ -71,7 +71,7 @@ public String getExtraDataString(@NotNull ExtraData data) { .orElse("No data"); } - public WrappedArgument getArgument() { + public WrappedArgument getArgument() { return argument; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index 01c2ac71..59ba3583 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -6,7 +6,7 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; -public class AlwaysSendDataConfig extends AbstractBotConfig { +public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; public AlwaysSendDataConfig() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java index 2a81bad7..cfb94613 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java @@ -7,7 +7,7 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; -public class LocatorBarConfig extends AbstractBotConfig { +public class LocatorBarConfig extends AbstractBotConfig { private boolean value; public LocatorBarConfig() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 75d3f481..042064c7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -9,7 +9,7 @@ import static net.minecraft.network.chat.Component.literal; -public class SimulationDistanceConfig extends AbstractBotConfig { +public class SimulationDistanceConfig extends AbstractBotConfig { public SimulationDistanceConfig() { super("simulation_distance", IntegerArgumentType.integer(2, 32), SimulationDistanceConfig::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index 5577ce2d..9580313a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -6,7 +6,7 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; -public class SkipSleepConfig extends AbstractBotConfig { +public class SkipSleepConfig extends AbstractBotConfig { public SkipSleepConfig() { super("skip_sleep", BoolArgumentType.bool(), SkipSleepConfig::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index 49257361..f155beda 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -7,7 +7,7 @@ import org.leavesmc.leaves.bot.agent.ExtraData; import org.leavesmc.leaves.command.CommandContext; -public class SpawnPhantomConfig extends AbstractBotConfig { +public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; public SpawnPhantomConfig() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index 109d9930..f3fb34a7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -1,36 +1,23 @@ package org.leavesmc.leaves.bot.agent.configs; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.EnumArgumentType; -public class TickTypeConfig extends AbstractBotConfig { +public class TickTypeConfig extends AbstractBotConfig { private ServerBot.TickType value; public TickTypeConfig() { - super("tick_type", StringArgumentType.word(), TickTypeConfig::new); + super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class), TickTypeConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.tickType; } @Override - public void applySuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { - builder.suggest("network"); - builder.suggest("entity_list"); - } - - @Override - public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException { - String raw = context.getString(getName()); - return switch (raw) { - case "network" -> ServerBot.TickType.NETWORK; - case "entity_list" -> ServerBot.TickType.ENTITY_LIST; - default -> throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); - }; + public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) { + return context.getArgument("tick_type", ServerBot.TickType.class); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java index c0e73f8c..dc134eed 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java @@ -6,8 +6,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java index 8d572553..21dee9f9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java @@ -4,9 +4,8 @@ import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.context.ParsedCommandNode; import com.mojang.brigadier.context.StringRange; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.CommandNode; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -64,13 +63,6 @@ public String getString(final String name) { return (V) source.getArgument(name, Object.class); } - @SuppressWarnings("unchecked") - public @NotNull V getCustomArgument(final Class> nodeClass) throws CommandSyntaxException { - String name = getNameForNode(nodeClass); - T raw = (T) source.getArgument(name, Object.class); - return CustomArgumentNode.transform(nodeClass, raw); - } - public V getArgumentOrDefault(final Class> nodeClass, final V defaultValue) { try { return getArgument(nodeClass); @@ -87,14 +79,6 @@ public V getArgumentOrDefault(final String name, final Class clazz, final } } - public V getCustomArgumentOrDefault(final Class> nodeClass, final V defaultValue) throws CommandSyntaxException { - try { - return getCustomArgument(nodeClass); - } catch (IllegalArgumentException e) { - return defaultValue; - } - } - public String getStringOrDefault(final String name, final String defaultValue) { return getArgumentOrDefault(name, String.class, defaultValue); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java index 033dcc97..3a640364 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java @@ -2,7 +2,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Method; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java index a270312f..bdf3d41c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java @@ -40,7 +40,7 @@ public static void registerPermissions(@NotNull List permissions) { } @DefaultQualifier(NonNull.class) - public static @NotNull List getListClosestMatchingLast(final String last, final Collection collection) { + public static List getListClosestMatchingLast(final String last, final Collection collection) { if (collection.isEmpty()) { return Collections.emptyList(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java deleted file mode 100644 index 75188f65..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentNode.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Map; - -public class CustomArgumentNode extends ArgumentNode { - @SuppressWarnings("rawtypes") - private static final Map, CustomArgumentType> TYPES = new HashMap<>(); - - protected CustomArgumentNode(String name, @NotNull CustomArgumentType argumentType) { - super(name, argumentType.getBaseArgumentType()); - TYPES.put(getClass(), argumentType); - } - - public static T transform(Class> nodeClass, B base) throws CommandSyntaxException { - @SuppressWarnings("unchecked") - CustomArgumentType type = (CustomArgumentType) TYPES.get(nodeClass); - if (type == null) { - throw new IllegalArgumentException("No custom argument type registered for " + nodeClass.getName()); - } - return type.transform(base); - } - - @Override - @SuppressWarnings("unchecked") - protected ArgumentBuilder compileBase() { - RequiredArgumentBuilder argumentBuilder = (RequiredArgumentBuilder) super.compileBase(); - - if (!overrideSuggestions()) { - CustomArgumentType customArgumentType = (CustomArgumentType) TYPES.get(getClass()); - argumentBuilder.suggests( - (context, builder) -> customArgumentType.getSuggestions(new CommandContext(context), builder) - ); - } - - return argumentBuilder; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java deleted file mode 100644 index 86d3c5f6..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CustomArgumentType.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; - -import java.util.concurrent.CompletableFuture; - -public interface CustomArgumentType { - ArgumentType getBaseArgumentType(); - - T transform(B value) throws CommandSyntaxException; - - CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException; -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java index 57f8fd9d..340f389c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java @@ -1,8 +1,8 @@ package org.leavesmc.leaves.command; import com.mojang.brigadier.builder.ArgumentBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; public class LiteralNode extends CommandNode { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java index 22d2b1e6..b2805c6e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java @@ -1,10 +1,9 @@ package org.leavesmc.leaves.command; -import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.MinecraftServer; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.PaperCommands; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -36,18 +35,16 @@ public boolean requires(@NotNull CommandSourceStack source) { @SuppressWarnings("unchecked") public void register() { - MinecraftServer.getServer() - .getCommands() - .getDispatcher() - .register((LiteralArgumentBuilder) compile()); + PaperCommands.INSTANCE.setValid(); + PaperCommands.INSTANCE.getDispatcher().register((LiteralArgumentBuilder) compile()); + PaperCommands.INSTANCE.invalidate(); Bukkit.getOnlinePlayers().forEach(org.bukkit.entity.Player::updateCommands); } public void unregister() { - CommandDispatcher dispatcher = MinecraftServer.getServer() - .getCommands() - .getDispatcher(); - dispatcher.getRoot().removeCommand(name); + PaperCommands.INSTANCE.setValid(); + PaperCommands.INSTANCE.getDispatcher().getRoot().removeCommand(name); + PaperCommands.INSTANCE.invalidate(); Bukkit.getOnlinePlayers().forEach(org.bukkit.entity.Player::updateCommands); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java index e41eb5c8..0c3326fb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java @@ -5,8 +5,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; import java.util.concurrent.CompletableFuture; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java similarity index 62% rename from leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java index ea55e25a..dff8c5ea 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java @@ -1,46 +1,47 @@ -package org.leavesmc.leaves.command.bot; +package org.leavesmc.leaves.command.arguments; import com.mojang.brigadier.arguments.ArgumentType; 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 io.papermc.paper.command.brigadier.argument.CustomArgumentType; import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CustomArgumentType; import java.util.Collection; import java.util.concurrent.CompletableFuture; -public class BotArgument implements CustomArgumentType { +public class BotArgumentType implements CustomArgumentType.Converted<@NotNull ServerBot, @NotNull String> { + @Override - public ArgumentType getBaseArgumentType() { - return StringArgumentType.word(); + public @NotNull CompletableFuture listSuggestions(com.mojang.brigadier.context.@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + Collection bots = BotList.INSTANCE.bots; + if (bots.isEmpty()) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("There are no bots in the server, create one first.")) + .buildFuture(); + } + bots.stream().map(ServerBot::getScoreboardName).forEach(builder::suggest); + return builder.buildFuture(); } @Override - public ServerBot transform(String value) throws CommandSyntaxException { - ServerBot bot = BotList.INSTANCE.getBotByName(value); + public ServerBot convert(String nativeType) throws CommandSyntaxException { + ServerBot bot = BotList.INSTANCE.getBotByName(nativeType); if (bot == null) { throw new CommandSyntaxException( CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), - Component.literal("Bot with name '" + value + "' does not exist") + Component.literal("Bot with name '" + nativeType + "' does not exist") ); } return bot; } @Override - public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { - Collection bots = BotList.INSTANCE.bots; - if (bots.isEmpty()) { - return builder - .suggest("", net.minecraft.network.chat.Component.literal("There are no bots in the server, create one first.")) - .buildFuture(); - } - bots.stream().map(ServerBot::getScoreboardName).forEach(builder::suggest); - return builder.buildFuture(); + public @NotNull ArgumentType<@NotNull String> getNativeType() { + return StringArgumentType.word(); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java new file mode 100644 index 00000000..ef90de03 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java @@ -0,0 +1,81 @@ +package org.leavesmc.leaves.command.arguments; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +@SuppressWarnings("ClassCanBeRecord") +public final class EnumArgumentType> implements CustomArgumentType.Converted<@NotNull T, @NotNull String> { + private final Class enumClass; + + @Contract(value = "_ -> new", pure = true) + public static > @NotNull EnumArgumentType fromEnum(Class enumClass) { + return new EnumArgumentType<>(enumClass); + } + + private EnumArgumentType(Class enumClass) { + this.enumClass = enumClass; + } + + @Override + public @NotNull T convert(@NotNull String nativeType) throws CommandSyntaxException { + try { + return Enum.valueOf(enumClass, nativeType.toUpperCase()); + } catch (IllegalArgumentException e) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + } + + @Override + public @NotNull CompletableFuture listSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + for (Enum value : enumClass.getEnumConstants()) { + String name = value.name().toLowerCase(); + if (name.startsWith(builder.getRemainingLowerCase())) { + builder.suggest(name); + } + } + return builder.buildFuture(); + } + + @Override + public @NotNull ArgumentType<@NotNull String> getNativeType() { + return StringArgumentType.word(); + } + + public Class enumClass() { + return enumClass; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + EnumArgumentType that = (EnumArgumentType) obj; + return Objects.equals(this.enumClass, that.enumClass); + } + + @Override + public int hashCode() { + return Objects.hash(enumClass); + } + + @Override + public String toString() { + return "EnumArgumentType[" + + "enumClass=" + enumClass + ']'; + } + +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java index d187e864..758fb015 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java @@ -1,7 +1,7 @@ package org.leavesmc.leaves.command.bot; import com.mojang.brigadier.builder.ArgumentBuilder; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.command.RootNode; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java index 0adae7a1..a46dfcc9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java @@ -1,6 +1,6 @@ package org.leavesmc.leaves.command.bot; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.command.LiteralNode; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java index 227fbf11..af2c3afd 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -1,12 +1,12 @@ package org.leavesmc.leaves.command.bot.subcommands; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.command.bot.subcommands.action.ListCommand; import org.leavesmc.leaves.command.bot.subcommands.action.StartCommand; @@ -24,10 +24,10 @@ public boolean requires(@NotNull CommandSourceStack source) { return LeavesConfig.modify.fakeplayer.canUseAction && super.requires(source); } - public static class BotArgument extends CustomArgumentNode { + public static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); + super("bot", new BotArgumentType()); children( StartCommand::new, StopCommand::new, @@ -35,8 +35,8 @@ private BotArgument() { ); } - public static @NotNull ServerBot getBot(@NotNull CommandContext context) throws CommandSyntaxException { - return context.getCustomArgument(BotArgument.class); + public static @NotNull ServerBot getBot(@NotNull CommandContext context) { + return context.getArgument(BotArgument.class); } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java index 10dc2e56..779b2b50 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java @@ -3,7 +3,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -11,9 +11,10 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Configs; import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; +import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CustomArgumentNode; import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.Collection; @@ -38,33 +39,33 @@ public boolean requires(@NotNull CommandSourceStack source) { return LeavesConfig.modify.fakeplayer.canModifyConfig && super.requires(source); } - private static class BotArgument extends CustomArgumentNode { + private static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); + super("bot", new BotArgumentType()); Configs.getConfigs().stream().map(this::configNodeCreator).forEach(this::children); } @Contract(pure = true) - private @NotNull Supplier configNodeCreator(AbstractBotConfig config) { + private @NotNull Supplier configNodeCreator(AbstractBotConfig config) { return () -> new ConfigNode<>(config); } - public static @NotNull ServerBot getBot(@NotNull CommandContext context) throws CommandSyntaxException { - return context.getCustomArgument(BotArgument.class); + public static @NotNull ServerBot getBot(@NotNull CommandContext context) { + return context.getArgument(BotArgument.class); } @Override - protected boolean execute(CommandContext context) throws CommandSyntaxException { + protected boolean execute(CommandContext context) { ServerBot bot = BotArgument.getBot(context); CommandSender sender = context.getSender(); - Collection> botConfigs = bot.getAllConfigs(); + Collection> botConfigs = bot.getAllConfigs(); sender.sendMessage(join(spaces(), text("Bot", GRAY), asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), text("configs:", GRAY) )); - for (AbstractBotConfig botConfig : botConfigs) { + for (AbstractBotConfig botConfig : botConfigs) { sender.sendMessage(join(spaces(), botConfig.getNameComponent(), text("=", GRAY), @@ -75,10 +76,10 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException } } - private static class ConfigNode extends LiteralNode { - private final AbstractBotConfig config; + private static class ConfigNode extends LiteralNode { + private final AbstractBotConfig config; - private ConfigNode(@NotNull AbstractBotConfig config) { + private ConfigNode(@NotNull AbstractBotConfig config) { super(config.getName()); this.config = config; } @@ -95,9 +96,9 @@ private ConfigNode(@NotNull AbstractBotConfig config) { } @Override - protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + protected boolean execute(@NotNull CommandContext context) { ServerBot bot = BotArgument.getBot(context); - AbstractBotConfig botConfig = bot.getConfig(config); + AbstractBotConfig botConfig = bot.getConfig(config); context.getSender().sendMessage(join(spaces(), text("Bot", GRAY), asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), @@ -111,7 +112,7 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE private boolean executeSet(CommandContext context) throws CommandSyntaxException { ServerBot bot = BotArgument.getBot(context); - AbstractBotConfig botConfig = bot.getConfig(config); + AbstractBotConfig botConfig = bot.getConfig(config); try { botConfig.setValue(botConfig.loadFromCommand(context)); } catch (ClassCastException e) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index df406a58..3b0ae0cf 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -2,19 +2,17 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; +import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.DimensionArgument; -import net.minecraft.commands.arguments.coordinates.Coordinates; -import net.minecraft.commands.arguments.coordinates.Vec3Argument; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Entity; +import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.BotCreateState; @@ -25,7 +23,6 @@ import org.leavesmc.leaves.event.bot.BotCreateEvent; import static net.kyori.adventure.text.Component.text; -import static net.minecraft.commands.arguments.DimensionArgument.getDimension; public class CreateCommand extends BotSubcommand { @@ -45,7 +42,7 @@ protected static boolean handleCreateCommand(@NotNull CommandContext context) th World world; try { - world = getDimension(context.getMojangContext(), "world").getWorld(); + world = context.getArgument(WorldArgument.class); } catch (IllegalArgumentException e) { if (!(sender instanceof Entity entity)) { sender.sendMessage(text("Must specify world and location when executed by console", NamedTextColor.RED)); @@ -55,10 +52,10 @@ protected static boolean handleCreateCommand(@NotNull CommandContext context) th } Location location = Bukkit.getWorlds().getFirst().getSpawnLocation(); - Coordinates coords = context.getArgumentOrDefault(LocationArgument.class, null); - if (coords != null) { - Vec3 vec3 = coords.getPosition(context.getSource()); - location = new Location(world, vec3.x, vec3.y, vec3.z); + FinePositionResolver positionResolver = context.getArgumentOrDefault(LocationArgument.class, null); + if (positionResolver != null) { + Vector vec3 = positionResolver.resolve(context.getSource()).toVector(); + location = new Location(world, vec3.getX(), vec3.getY(), vec3.getZ()); } else if (sender instanceof Entity entity) { location = entity.getLocation(); } @@ -122,9 +119,9 @@ protected boolean execute(CommandContext context) throws CommandSyntaxException } } - private static class WorldArgument extends ArgumentNode { + private static class WorldArgument extends ArgumentNode { private WorldArgument() { - super("world", DimensionArgument.dimension()); + super("world", ArgumentTypes.world()); children(LocationArgument::new); } @@ -134,9 +131,9 @@ public boolean requires(@NotNull CommandSourceStack source) { } } - private static class LocationArgument extends ArgumentNode { + private static class LocationArgument extends ArgumentNode { private LocationArgument() { - super("location", Vec3Argument.vec3(true)); + super("location", ArgumentTypes.finePosition()); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java index 3033a84f..3464717d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java @@ -2,10 +2,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; import net.kyori.adventure.text.Component; -import net.minecraft.commands.arguments.DimensionArgument; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import org.bukkit.Bukkit; import org.bukkit.World; @@ -28,8 +26,6 @@ import static net.kyori.adventure.text.JoinConfiguration.noSeparators; import static net.kyori.adventure.text.event.HoverEvent.showText; import static net.kyori.adventure.text.format.NamedTextColor.*; -import static net.minecraft.commands.arguments.DimensionArgument.getDimension; - public class ListCommand extends BotSubcommand { @@ -76,16 +72,16 @@ protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxE ); } - private static class WorldArgument extends ArgumentNode { + private static class WorldArgument extends ArgumentNode { private WorldArgument() { - super("world", DimensionArgument.dimension()); + super("world", ArgumentTypes.world()); } @Override - protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { - ServerLevel dimension = getDimension(context.getMojangContext(), "world"); - Component botListMessage = getBotListMessage(dimension.getWorld()); + protected boolean execute(@NotNull CommandContext context) { + World world = context.getArgument(WorldArgument.class); + Component botListMessage = getBotListMessage(world); CommandSender sender = context.getSender(); if (botListMessage == null) { sender.sendMessage(text("No bots in that world", RED)); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java index 699848f6..7a5e3481 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -4,8 +4,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; 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; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java index 09df5362..01225a57 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -11,7 +11,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.event.bot.BotRemoveEvent; import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; @@ -41,15 +41,15 @@ private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender return success; } - private static class BotArgument extends CustomArgumentNode { + private static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); + super("bot", new BotArgumentType()); children(RemoveTimeArgument::new); } @Override - protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { - ServerBot bot = context.getCustomArgument(BotArgument.class); + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = context.getArgument(BotArgument.class); return removeBot(bot, context.getSender()); } } @@ -64,7 +64,7 @@ private RemoveTimeArgument() { protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { String removeTimeStr = context.getArgument("remove_time", String.class); int removeTimeSeconds = parseRemoveTime(removeTimeStr); - ServerBot bot = context.getCustomArgument(BotArgument.class); + ServerBot bot = context.getArgument(BotArgument.class); CommandSender sender = context.getSender(); boolean isReschedule = bot.removeTaskId != -1; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java index 218c06da..2d243cb5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -1,15 +1,15 @@ package org.leavesmc.leaves.command.bot.subcommands; -import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; 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.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CustomArgumentNode; +import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.event.bot.BotRemoveEvent; @@ -30,15 +30,15 @@ public boolean requires(@NotNull CommandSourceStack source) { return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad && super.requires(source); } - private static class BotArgument extends CustomArgumentNode { + private static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new org.leavesmc.leaves.command.bot.BotArgument()); + super("bot", new BotArgumentType()); } @Override - protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { - ServerBot bot = context.getCustomArgument(BotArgument.class); + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = context.getArgument(BotArgument.class); CommandSender sender = context.getSender(); BotList botList = BotList.INSTANCE; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java index 8a7b0a18..126c8ea2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -3,7 +3,7 @@ import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.Contract; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java index fa20c4c8..006b0f19 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java @@ -1,6 +1,6 @@ package org.leavesmc.leaves.command.leaves; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.command.LiteralNode; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java index 9c91bb93..86aa3a54 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java @@ -1,7 +1,7 @@ package org.leavesmc.leaves.command.leaves.subcommands; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.commands.CommandSourceStack; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java index 5d32cbc4..2d7505b2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -31,7 +31,7 @@ private static class PathArgument extends ArgumentNode { private PathArgument() { super("path", StringArgumentType.string()); - children(ConfigCommand.ValueArgument::new); + children(ValueArgument::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java index 4329415d..5c14da8e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java @@ -1,8 +1,8 @@ package org.leavesmc.leaves.command.leaves.subcommands; +import io.papermc.paper.command.brigadier.CommandSourceStack; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; -import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; import net.minecraft.world.item.DyeColor; import org.bukkit.command.CommandSender; From 42845d1f602005347c54653c8c08861f83ade664 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Wed, 24 Sep 2025 13:09:15 +0800 Subject: [PATCH 25/29] refactor: use paper command api --- .../leavesmc/leaves/command/arguments/BotArgumentType.java | 7 +++++++ .../leaves/command/bot/subcommands/ActionCommand.java | 2 +- .../leaves/command/bot/subcommands/ConfigCommand.java | 2 +- .../leaves/command/bot/subcommands/RemoveCommand.java | 2 +- .../leaves/command/bot/subcommands/SaveCommand.java | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java index dff8c5ea..f4518812 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java @@ -16,6 +16,13 @@ public class BotArgumentType implements CustomArgumentType.Converted<@NotNull ServerBot, @NotNull String> { + private BotArgumentType() { + } + + public static @NotNull BotArgumentType bot() { + return new BotArgumentType(); + } + @Override public @NotNull CompletableFuture listSuggestions(com.mojang.brigadier.context.@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { Collection bots = BotList.INSTANCE.bots; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java index af2c3afd..d0736996 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -27,7 +27,7 @@ public boolean requires(@NotNull CommandSourceStack source) { public static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new BotArgumentType()); + super("bot", BotArgumentType.bot()); children( StartCommand::new, StopCommand::new, diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java index 779b2b50..98fb98c4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java @@ -42,7 +42,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new BotArgumentType()); + super("bot", BotArgumentType.bot()); Configs.getConfigs().stream().map(this::configNodeCreator).forEach(this::children); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java index 01225a57..67f75ad5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -43,7 +43,7 @@ private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender private static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new BotArgumentType()); + super("bot", BotArgumentType.bot()); children(RemoveTimeArgument::new); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java index 2d243cb5..f0dac9af 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -33,7 +33,7 @@ public boolean requires(@NotNull CommandSourceStack source) { private static class BotArgument extends ArgumentNode { private BotArgument() { - super("bot", new BotArgumentType()); + super("bot", BotArgumentType.bot()); } @Override From d89a099a0dad27c27af82909e32dc1ed14942ed0 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Wed, 24 Sep 2025 13:37:47 +0800 Subject: [PATCH 26/29] feat: use raycasting in mount action --- .../bot/agent/actions/ServerMountAction.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java index 39da096b..d39e0681 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java @@ -1,8 +1,7 @@ package org.leavesmc.leaves.bot.agent.actions; -import net.minecraft.world.entity.Entity; import org.bukkit.Location; -import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftVehicle; import org.bukkit.entity.Vehicle; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; @@ -22,14 +21,17 @@ public boolean doTick(@NotNull ServerBot bot) { Location center = bot.getBukkitEntity().getLocation(); List vehicles = center.getNearbyEntitiesByType( Vehicle.class, - 4, - vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 3 + bot.entityInteractionRange() ).stream().sorted(Comparator.comparingDouble( (vehicle) -> center.distanceSquared(vehicle.getLocation()) )).toList(); for (Vehicle vehicle : vehicles) { - if (bot.startRiding(((CraftEntity) vehicle).getHandle(), false)) { + CraftVehicle craftVehicle = (CraftVehicle) vehicle; + if (!bot.hasLineOfSight(craftVehicle.getHandle())) { + continue; + } + if (bot.startRiding(craftVehicle.getHandle(), false)) { return true; } } @@ -41,10 +43,4 @@ public boolean doTick(@NotNull ServerBot bot) { public Object asCraft() { return new CraftMountAction(this); } - - private double manhattanDistance(@NotNull Entity entity1, @NotNull Entity entity2) { - return Math.abs(entity1.getX() - entity2.getX()) + - Math.abs(entity1.getY() - entity2.getY()) + - Math.abs(entity1.getZ() - entity2.getZ()); - } } From b6587773411d2bbb5bdfbb1bbca6c46f54186dc0 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Wed, 24 Sep 2025 23:33:31 +0800 Subject: [PATCH 27/29] feat: try to impl custom --- .../leaves/command/LeavesCommandContext.java | 57 +++++++++++++++++++ .../leaves/command/LeavesWrappedArgument.java | 35 ++++++++++++ .../leaves/entity/bot/BotManager.java | 5 ++ .../entity/bot/action/CustomBotAction.java | 51 +++++++++++++++++ .../org/leavesmc/leaves/util}/ExtraData.java | 2 +- .../leavesmc/leaves/bot/agent/Actions.java | 4 ++ .../bot/agent/actions/AbstractBotAction.java | 6 +- .../agent/actions/AbstractTimerBotAction.java | 6 +- .../agent/actions/AbstractUseBotAction.java | 6 +- .../agent/actions/ServerCustomBotAction.java | 54 ++++++++++++++++++ .../bot/agent/actions/ServerLookAction.java | 4 +- .../bot/agent/actions/ServerMoveAction.java | 6 +- .../agent/actions/ServerRotationAction.java | 6 +- .../bot/agent/configs/AbstractBotConfig.java | 8 +-- .../agent/configs/AlwaysSendDataConfig.java | 4 +- .../bot/agent/configs/LocatorBarConfig.java | 4 +- .../configs/SimulationDistanceConfig.java | 6 +- .../bot/agent/configs/SkipSleepConfig.java | 4 +- .../bot/agent/configs/SpawnPhantomConfig.java | 6 +- .../bot/agent/configs/TickTypeConfig.java | 4 +- .../leaves/command/CommandContext.java | 4 +- .../leaves/command/WrappedArgument.java | 15 +---- .../bot/subcommands/ActionCommand.java | 1 + .../bot/subcommands/CreateCommand.java | 1 + .../command/bot/subcommands/ListCommand.java | 1 + .../command/bot/subcommands/LoadCommand.java | 1 + .../command/bot/subcommands/SaveCommand.java | 1 + .../bot/subcommands/action/ListCommand.java | 1 + .../bot/subcommands/action/StartCommand.java | 1 + .../bot/subcommands/action/StopCommand.java | 1 + .../subcommands/BlockUpdateCommand.java | 1 + .../leaves/subcommands/ConfigCommand.java | 1 + .../leaves/subcommands/ReloadCommand.java | 1 + .../leaves/entity/bot/CraftBotManager.java | 17 ++++++ .../bot/actions/CraftCustomBotAction.java | 11 ++++ 35 files changed, 284 insertions(+), 52 deletions(-) create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java rename {leaves-server/src/main/java/org/leavesmc/leaves/bot/agent => leaves-api/src/main/java/org/leavesmc/leaves/util}/ExtraData.java (85%) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java b/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java new file mode 100644 index 00000000..53f4fa22 --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java @@ -0,0 +1,57 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.RedirectModifier; +import com.mojang.brigadier.context.ParsedCommandNode; +import com.mojang.brigadier.context.StringRange; +import com.mojang.brigadier.tree.CommandNode; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface LeavesCommandContext { + + com.mojang.brigadier.context.CommandContext getChild(); + + com.mojang.brigadier.context.CommandContext getLastChild(); + + Command getCommand(); + + CommandSourceStack getSource(); + + CommandSender getSender(); + + @NotNull V getArgument(final String name, final Class clazz); + + int getInteger(final String name); + + boolean getBoolean(final String name); + + String getString(final String name); + + V getArgumentOrDefault(final String name, final Class clazz, final V defaultValue); + + String getStringOrDefault(final String name, final String defaultValue); + + int getIntegerOrDefault(final String name, final int defaultValue); + + float getFloatOrDefault(final String name, final float defaultValue); + + RedirectModifier getRedirectModifier(); + + StringRange getRange(); + + String getInput(); + + CommandNode getRootNode(); + + List> getNodes(); + + boolean hasNodes(); + + boolean isForked(); + + com.mojang.brigadier.context.CommandContext rawContext(); +} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java b/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java new file mode 100644 index 00000000..7ecdd4f0 --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java @@ -0,0 +1,35 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import java.util.concurrent.CompletableFuture; + +@SuppressWarnings("unused") +public interface LeavesWrappedArgument { + + LeavesWrappedArgument suggestsAsync(AsyncSuggestionProvider provider); + + LeavesWrappedArgument suggests(SuggestionApplier provider); + + LeavesWrappedArgument setOptional(boolean optional); + + boolean isOptional(); + + @FunctionalInterface + interface SuggestionApplier { + void applySuggestions(final LeavesCommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } + + @FunctionalInterface + interface AsyncSuggestionProvider { + CompletableFuture getSuggestions(final LeavesCommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } + + interface ArgumentHandler { + LeavesWrappedArgument create(String name, com.mojang.brigadier.arguments.ArgumentType type); + + void fork(int forkId); + } +} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java index c434364f..2e671cc5 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.entity.bot.action.BotAction; +import org.leavesmc.leaves.entity.bot.action.CustomBotAction; import java.util.Collection; import java.util.UUID; @@ -45,4 +46,8 @@ public interface BotManager { > T newAction(@NotNull Class type); BotCreator botCreator(@NotNull String realName, @NotNull Location location); + + boolean registerCustomAction(@NotNull CustomBotAction customBotAction, boolean resendCommandTree); + + boolean registerCustomAction(@NotNull CustomBotAction customBotAction); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java new file mode 100644 index 00000000..0f7d35ff --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java @@ -0,0 +1,51 @@ +package org.leavesmc.leaves.entity.bot.action; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.LeavesWrappedArgument; +import org.leavesmc.leaves.entity.bot.Bot; +import org.leavesmc.leaves.util.ExtraData; + +@SuppressWarnings("unused") +public abstract class CustomBotAction { + private LeavesWrappedArgument.ArgumentHandler factory; + + public abstract boolean doTick(@NotNull Bot bot); + + public abstract String getName(); + + public void init() { + } + + public void loadCommand(CommandContext context) { + } + + public void provideActionData(@NotNull ExtraData data) { + } + + public void provideArgumentFactory(LeavesWrappedArgument.ArgumentHandler factory) { + this.factory = factory; + } + + protected LeavesWrappedArgument addArgument(String name, ArgumentType type) { + if (factory == null) { + throw new IllegalStateException("Argument factory not provided! Are you calling addArgument() outside of init() method?"); + } + return factory.create(name, type); + } + + protected void fork(int forkId) { + if (factory == null) { + throw new IllegalStateException("Argument factory not provided! Are you calling fork() outside of init() method?"); + } + factory.fork(forkId); + } + + @ApiStatus.Internal + public interface InternalCustomBotAction extends BotAction { + + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java b/leaves-api/src/main/java/org/leavesmc/leaves/util/ExtraData.java similarity index 85% rename from leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java rename to leaves-api/src/main/java/org/leavesmc/leaves/util/ExtraData.java index 46c852ab..86143042 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/util/ExtraData.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.bot.agent; +package org.leavesmc.leaves.util; import org.apache.commons.lang3.tuple.Pair; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index 214165eb..0bc418c7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -38,6 +38,10 @@ public class Actions { register(new ServerSwapAction(), SwapAction.class); } + public static boolean register(@NotNull CustomBotAction customBotAction) { + return register(new ServerCustomBotAction(customBotAction), customBotAction.getClass()); + } + public static boolean register(@NotNull AbstractBotAction action, Class type) { if (!actionsByName.containsKey(action.getName())) { actionsByName.put(action.getName(), action); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index b59b0be5..bbd12ff1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -8,8 +8,8 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.WrappedArgument; import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; import org.leavesmc.leaves.event.bot.BotActionStopEvent; @@ -181,7 +181,7 @@ public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) { } @SuppressWarnings("RedundantThrows") - public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { + public void loadCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException { } @NotNull diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index 817b5ec0..ecf4d4e3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -2,8 +2,8 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; import java.util.function.Supplier; @@ -22,7 +22,7 @@ public AbstractTimerBotAction(String name, Supplier creator) { } @Override - public void loadCommand(@NotNull CommandContext context) { + public void loadCommand(@NotNull LeavesCommandContext context) { this.setStartDelayTick(context.getIntegerOrDefault("delay", 0)); this.setDoIntervalTick(context.getIntegerOrDefault("interval", 20)); this.setDoNumber(context.getIntegerOrDefault("do_number", 1)); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 2d2fa41b..86a38e68 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -5,8 +5,8 @@ import net.minecraft.world.InteractionResult; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.event.bot.BotActionStopEvent; import java.util.function.Supplier; @@ -30,7 +30,7 @@ public AbstractUseBotAction(String name, Supplier supplier) { } @Override - public void loadCommand(@NotNull CommandContext context) { + public void loadCommand(@NotNull LeavesCommandContext context) { super.loadCommand(context); this.useTickTimeout = context.getIntegerOrDefault("use_timeout", -1); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java new file mode 100644 index 00000000..d051e9b2 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java @@ -0,0 +1,54 @@ +package org.leavesmc.leaves.bot.agent.actions; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.LeavesWrappedArgument; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.entity.bot.action.CustomBotAction; +import org.leavesmc.leaves.entity.bot.actions.CraftCustomBotAction; + +public class ServerCustomBotAction extends AbstractBotAction { + private final CustomBotAction customBotAction; + + public ServerCustomBotAction(@NotNull CustomBotAction customBotAction) { + super(customBotAction.getName(), () -> new ServerCustomBotAction(customBotAction)); + this.customBotAction = customBotAction; + customBotAction.provideArgumentFactory(new LeavesWrappedArgument.ArgumentHandler() { + @Override + public LeavesWrappedArgument create(String name, ArgumentType type) { + return addArgument(name, type); + } + + @Override + public void fork(int forkId) { + ServerCustomBotAction.this.fork(forkId); + } + }); + customBotAction.init(); + } + + @Override + public String getActionDataString(@NotNull ExtraData data) { + customBotAction.provideActionData(data); + return super.getActionDataString(data); + } + + @Override + public void loadCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException { + super.loadCommand(context); + customBotAction.loadCommand(context.rawContext()); + } + + @Override + public boolean doTick(@NotNull ServerBot bot) { + return customBotAction.doTick(bot.getBukkitEntity()); + } + + @Override + public Object asCraft() { + return new CraftCustomBotAction(this); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index 8333826d..0c499365 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -13,7 +13,7 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; public class ServerLookAction extends AbstractBotAction { @@ -31,7 +31,7 @@ public ServerLookAction() { } @Override - public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { + public void loadCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException { PlayerSelectorArgumentResolver playerSelectorResolver = context.getArgumentOrDefault("player", PlayerSelectorArgumentResolver.class, null); FinePositionResolver positionResolver = context.getArgumentOrDefault("location", FinePositionResolver.class, null); CommandSourceStack source = context.getSource(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 4023b469..a7a1509e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -2,8 +2,8 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.arguments.EnumArgumentType; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; @@ -18,7 +18,7 @@ public ServerMoveAction() { } @Override - public void loadCommand(@NotNull CommandContext context) { + public void loadCommand(@NotNull LeavesCommandContext context) { this.direction = context.getArgument("direction", MoveDirection.class); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 85f51064..3be55610 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -7,8 +7,8 @@ import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; import java.text.DecimalFormat; @@ -47,7 +47,7 @@ public ServerRotationAction() { private float pitch = 0.0f; @Override - public void loadCommand(@NotNull CommandContext context) { + public void loadCommand(@NotNull LeavesCommandContext context) { CommandSender sender = context.getSender(); if (sender instanceof Entity entity) { this.yaw = entity.getYaw(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java index 7b87332d..75f6a655 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -9,8 +9,8 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.WrappedArgument; import java.lang.reflect.Method; @@ -34,7 +34,7 @@ public AbstractBotConfig(String name, ArgumentType type, Supplier creator) } @SuppressWarnings("RedundantThrows") - public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { + public void applySuggestions(final LeavesCommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { } public AbstractBotConfig setBot(ServerBot bot) { @@ -50,7 +50,7 @@ public E create() { public abstract void setValue(T value) throws CommandSyntaxException; - public abstract T loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; + public abstract T loadFromCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException; public String getName() { return name; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index 59ba3583..808d6d53 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; @@ -25,7 +25,7 @@ public void setValue(Boolean value) { } @Override - public Boolean loadFromCommand(@NotNull CommandContext context) { + public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java index cfb94613..017a4f2f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java @@ -5,7 +5,7 @@ import net.minecraft.server.waypoints.ServerWaypointManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; public class LocatorBarConfig extends AbstractBotConfig { private boolean value; @@ -32,7 +32,7 @@ public void setValue(@NotNull Boolean value) throws IllegalArgumentException { } @Override - public Boolean loadFromCommand(@NotNull CommandContext context) { + public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 042064c7..2451ad03 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -5,7 +5,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import static net.minecraft.network.chat.Component.literal; @@ -16,7 +16,7 @@ public SimulationDistanceConfig() { } @Override - public void applySuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { + public void applySuggestions(LeavesCommandContext context, @NotNull SuggestionsBuilder builder) { builder.suggest("2", literal("Minimum simulation distance")); builder.suggest("8"); builder.suggest("12"); @@ -35,7 +35,7 @@ public void setValue(Integer value) { } @Override - public Integer loadFromCommand(@NotNull CommandContext context) { + public Integer loadFromCommand(@NotNull LeavesCommandContext context) { return context.getInteger(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index 9580313a..9dbcb8fd 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; public class SkipSleepConfig extends AbstractBotConfig { @@ -23,7 +23,7 @@ public void setValue(Boolean value) throws IllegalArgumentException { } @Override - public Boolean loadFromCommand(@NotNull CommandContext context) { + public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index f155beda..cd7dfbf4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -4,8 +4,8 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.ExtraData; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.util.ExtraData; +import org.leavesmc.leaves.command.LeavesCommandContext; public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; @@ -32,7 +32,7 @@ public String getExtraDataString(@NotNull ExtraData data) { } @Override - public Boolean loadFromCommand(@NotNull CommandContext context) { + public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index f3fb34a7..6027e41a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.arguments.EnumArgumentType; public class TickTypeConfig extends AbstractBotConfig { @@ -16,7 +16,7 @@ public TickTypeConfig() { } @Override - public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) { + public ServerBot.TickType loadFromCommand(@NotNull LeavesCommandContext context) { return context.getArgument("tick_type", ServerBot.TickType.class); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java index 21dee9f9..5d3a0a8f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java @@ -14,7 +14,7 @@ import static org.leavesmc.leaves.command.CommandNode.getNameForNode; @SuppressWarnings({"ClassCanBeRecord", "unused"}) -public class CommandContext { +public class CommandContext implements LeavesCommandContext { private final com.mojang.brigadier.context.CommandContext source; public CommandContext(com.mojang.brigadier.context.CommandContext source) { @@ -119,7 +119,7 @@ public boolean isForked() { return source.isForked(); } - public com.mojang.brigadier.context.CommandContext getMojangContext() { + public com.mojang.brigadier.context.CommandContext rawContext() { return source; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java index 0c3326fb..b0f6e4a7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java @@ -2,15 +2,12 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; import java.util.concurrent.CompletableFuture; -public class WrappedArgument { +public class WrappedArgument implements LeavesWrappedArgument { private final String name; private final ArgumentType type; private AsyncSuggestionProvider asyncSuggestionProvider = null; @@ -55,14 +52,4 @@ public RequiredArgumentBuilder compile() { } return builder; } - - @FunctionalInterface - public interface SuggestionApplier { - void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; - } - - @FunctionalInterface - public interface AsyncSuggestionProvider { - CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java index d0736996..99085738 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -6,6 +6,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.command.bot.subcommands.action.ListCommand; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index 3b0ae0cf..70555b4d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -19,6 +19,7 @@ import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.event.bot.BotCreateEvent; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java index 3464717d..77a85d9a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java @@ -16,6 +16,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java index 7a5e3481..6c8d942d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -13,6 +13,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.Set; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java index f0dac9af..cf7b5056 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -9,6 +9,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.event.bot.BotRemoveEvent; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java index 1547891e..ea2d02cb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java @@ -6,6 +6,7 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java index 126c8ea2..8f9ea4d0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -12,6 +12,7 @@ import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.WrappedArgument; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java index 16d75583..dc48f7b3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java @@ -11,6 +11,7 @@ import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; import org.leavesmc.leaves.event.bot.BotActionStopEvent; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java index 86aa3a54..a47e6cbd 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java index 2d7505b2..bb5eeb1e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.CommandUtils; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import org.leavesmc.leaves.config.GlobalConfigManager; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java index bf4d4428..1867c983 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import static net.kyori.adventure.text.Component.text; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java index 550985c4..01bb157c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java @@ -2,7 +2,9 @@ import com.google.common.collect.Lists; import net.minecraft.server.MinecraftServer; +import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.BotCreateState; @@ -11,6 +13,7 @@ import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; +import org.leavesmc.leaves.entity.bot.action.CustomBotAction; import org.leavesmc.leaves.event.bot.BotCreateEvent; import java.util.Collection; @@ -71,4 +74,18 @@ public > T newAction(@NotNull Class type) { public BotCreator botCreator(@NotNull String realName, @NotNull Location location) { return BotCreateState.builder(realName, location).createReason(BotCreateEvent.CreateReason.PLUGIN); } + + @Override + public boolean registerCustomAction(@NotNull CustomBotAction customBotAction, boolean resendCommandTree) { + boolean result = Actions.register(customBotAction); + if (result && resendCommandTree) { + Bukkit.getOnlinePlayers().forEach(Player::updateCommands); + } + return result; + } + + @Override + public boolean registerCustomAction(@NotNull CustomBotAction customBotAction) { + return registerCustomAction(customBotAction, true); + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java new file mode 100644 index 00000000..730590db --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java @@ -0,0 +1,11 @@ +package org.leavesmc.leaves.entity.bot.actions; + +import org.leavesmc.leaves.bot.agent.actions.ServerCustomBotAction; +import org.leavesmc.leaves.entity.bot.action.CustomBotAction; + +public class CraftCustomBotAction extends CraftBotAction implements CustomBotAction.InternalCustomBotAction { + + public CraftCustomBotAction(ServerCustomBotAction serverAction) { + super(serverAction, CraftCustomBotAction::new); + } +} From 8daf717ce12117f641a35b2b13c3a186bb5e5985 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Thu, 25 Sep 2025 13:40:45 +0800 Subject: [PATCH 28/29] Revert "feat: try to impl custom" This reverts commit b6587773411d2bbb5bdfbb1bbca6c46f54186dc0. --- .../leaves/command/LeavesCommandContext.java | 57 ------------------- .../leaves/command/LeavesWrappedArgument.java | 35 ------------ .../leaves/entity/bot/BotManager.java | 5 -- .../entity/bot/action/CustomBotAction.java | 51 ----------------- .../leavesmc/leaves/bot/agent/Actions.java | 4 -- .../leavesmc/leaves/bot/agent}/ExtraData.java | 2 +- .../bot/agent/actions/AbstractBotAction.java | 6 +- .../agent/actions/AbstractTimerBotAction.java | 6 +- .../agent/actions/AbstractUseBotAction.java | 6 +- .../agent/actions/ServerCustomBotAction.java | 54 ------------------ .../bot/agent/actions/ServerLookAction.java | 4 +- .../bot/agent/actions/ServerMoveAction.java | 6 +- .../agent/actions/ServerRotationAction.java | 6 +- .../bot/agent/configs/AbstractBotConfig.java | 8 +-- .../agent/configs/AlwaysSendDataConfig.java | 4 +- .../bot/agent/configs/LocatorBarConfig.java | 4 +- .../configs/SimulationDistanceConfig.java | 6 +- .../bot/agent/configs/SkipSleepConfig.java | 4 +- .../bot/agent/configs/SpawnPhantomConfig.java | 6 +- .../bot/agent/configs/TickTypeConfig.java | 4 +- .../leaves/command/CommandContext.java | 4 +- .../leaves/command/WrappedArgument.java | 15 ++++- .../bot/subcommands/ActionCommand.java | 1 - .../bot/subcommands/CreateCommand.java | 1 - .../command/bot/subcommands/ListCommand.java | 1 - .../command/bot/subcommands/LoadCommand.java | 1 - .../command/bot/subcommands/SaveCommand.java | 1 - .../bot/subcommands/action/ListCommand.java | 1 - .../bot/subcommands/action/StartCommand.java | 1 - .../bot/subcommands/action/StopCommand.java | 1 - .../subcommands/BlockUpdateCommand.java | 1 - .../leaves/subcommands/ConfigCommand.java | 1 - .../leaves/subcommands/ReloadCommand.java | 1 - .../leaves/entity/bot/CraftBotManager.java | 17 ------ .../bot/actions/CraftCustomBotAction.java | 11 ---- 35 files changed, 52 insertions(+), 284 deletions(-) delete mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java delete mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java delete mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java rename {leaves-api/src/main/java/org/leavesmc/leaves/util => leaves-server/src/main/java/org/leavesmc/leaves/bot/agent}/ExtraData.java (85%) delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java b/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java deleted file mode 100644 index 53f4fa22..00000000 --- a/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesCommandContext.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.RedirectModifier; -import com.mojang.brigadier.context.ParsedCommandNode; -import com.mojang.brigadier.context.StringRange; -import com.mojang.brigadier.tree.CommandNode; -import io.papermc.paper.command.brigadier.CommandSourceStack; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public interface LeavesCommandContext { - - com.mojang.brigadier.context.CommandContext getChild(); - - com.mojang.brigadier.context.CommandContext getLastChild(); - - Command getCommand(); - - CommandSourceStack getSource(); - - CommandSender getSender(); - - @NotNull V getArgument(final String name, final Class clazz); - - int getInteger(final String name); - - boolean getBoolean(final String name); - - String getString(final String name); - - V getArgumentOrDefault(final String name, final Class clazz, final V defaultValue); - - String getStringOrDefault(final String name, final String defaultValue); - - int getIntegerOrDefault(final String name, final int defaultValue); - - float getFloatOrDefault(final String name, final float defaultValue); - - RedirectModifier getRedirectModifier(); - - StringRange getRange(); - - String getInput(); - - CommandNode getRootNode(); - - List> getNodes(); - - boolean hasNodes(); - - boolean isForked(); - - com.mojang.brigadier.context.CommandContext rawContext(); -} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java b/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java deleted file mode 100644 index 7ecdd4f0..00000000 --- a/leaves-api/src/main/java/org/leavesmc/leaves/command/LeavesWrappedArgument.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; - -import java.util.concurrent.CompletableFuture; - -@SuppressWarnings("unused") -public interface LeavesWrappedArgument { - - LeavesWrappedArgument suggestsAsync(AsyncSuggestionProvider provider); - - LeavesWrappedArgument suggests(SuggestionApplier provider); - - LeavesWrappedArgument setOptional(boolean optional); - - boolean isOptional(); - - @FunctionalInterface - interface SuggestionApplier { - void applySuggestions(final LeavesCommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; - } - - @FunctionalInterface - interface AsyncSuggestionProvider { - CompletableFuture getSuggestions(final LeavesCommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; - } - - interface ArgumentHandler { - LeavesWrappedArgument create(String name, com.mojang.brigadier.arguments.ArgumentType type); - - void fork(int forkId); - } -} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java index 2e671cc5..c434364f 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java @@ -4,7 +4,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.entity.bot.action.BotAction; -import org.leavesmc.leaves.entity.bot.action.CustomBotAction; import java.util.Collection; import java.util.UUID; @@ -46,8 +45,4 @@ public interface BotManager { > T newAction(@NotNull Class type); BotCreator botCreator(@NotNull String realName, @NotNull Location location); - - boolean registerCustomAction(@NotNull CustomBotAction customBotAction, boolean resendCommandTree); - - boolean registerCustomAction(@NotNull CustomBotAction customBotAction); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java deleted file mode 100644 index 0f7d35ff..00000000 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/action/CustomBotAction.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.leavesmc.leaves.entity.bot.action; - -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import io.papermc.paper.command.brigadier.CommandSourceStack; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.command.LeavesWrappedArgument; -import org.leavesmc.leaves.entity.bot.Bot; -import org.leavesmc.leaves.util.ExtraData; - -@SuppressWarnings("unused") -public abstract class CustomBotAction { - private LeavesWrappedArgument.ArgumentHandler factory; - - public abstract boolean doTick(@NotNull Bot bot); - - public abstract String getName(); - - public void init() { - } - - public void loadCommand(CommandContext context) { - } - - public void provideActionData(@NotNull ExtraData data) { - } - - public void provideArgumentFactory(LeavesWrappedArgument.ArgumentHandler factory) { - this.factory = factory; - } - - protected LeavesWrappedArgument addArgument(String name, ArgumentType type) { - if (factory == null) { - throw new IllegalStateException("Argument factory not provided! Are you calling addArgument() outside of init() method?"); - } - return factory.create(name, type); - } - - protected void fork(int forkId) { - if (factory == null) { - throw new IllegalStateException("Argument factory not provided! Are you calling fork() outside of init() method?"); - } - factory.fork(forkId); - } - - @ApiStatus.Internal - public interface InternalCustomBotAction extends BotAction { - - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index 0bc418c7..214165eb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -38,10 +38,6 @@ public class Actions { register(new ServerSwapAction(), SwapAction.class); } - public static boolean register(@NotNull CustomBotAction customBotAction) { - return register(new ServerCustomBotAction(customBotAction), customBotAction.getClass()); - } - public static boolean register(@NotNull AbstractBotAction action, Class type) { if (!actionsByName.containsKey(action.getName())) { actionsByName.put(action.getName(), action); diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/util/ExtraData.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java similarity index 85% rename from leaves-api/src/main/java/org/leavesmc/leaves/util/ExtraData.java rename to leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java index 86143042..46c852ab 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/util/ExtraData.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.util; +package org.leavesmc.leaves.bot.agent; import org.apache.commons.lang3.tuple.Pair; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index bbd12ff1..b59b0be5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -8,8 +8,8 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.WrappedArgument; import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; import org.leavesmc.leaves.event.bot.BotActionStopEvent; @@ -181,7 +181,7 @@ public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) { } @SuppressWarnings("RedundantThrows") - public void loadCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException { + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { } @NotNull diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java index ecf4d4e3..817b5ec0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -2,8 +2,8 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import java.util.function.Supplier; @@ -22,7 +22,7 @@ public AbstractTimerBotAction(String name, Supplier creator) { } @Override - public void loadCommand(@NotNull LeavesCommandContext context) { + public void loadCommand(@NotNull CommandContext context) { this.setStartDelayTick(context.getIntegerOrDefault("delay", 0)); this.setDoIntervalTick(context.getIntegerOrDefault("interval", 20)); this.setDoNumber(context.getIntegerOrDefault("do_number", 1)); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index 86a38e68..2d2fa41b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -5,8 +5,8 @@ import net.minecraft.world.InteractionResult; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.event.bot.BotActionStopEvent; import java.util.function.Supplier; @@ -30,7 +30,7 @@ public AbstractUseBotAction(String name, Supplier supplier) { } @Override - public void loadCommand(@NotNull LeavesCommandContext context) { + public void loadCommand(@NotNull CommandContext context) { super.loadCommand(context); this.useTickTimeout = context.getIntegerOrDefault("use_timeout", -1); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java deleted file mode 100644 index d051e9b2..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerCustomBotAction.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.leavesmc.leaves.bot.agent.actions; - -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesWrappedArgument; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; -import org.leavesmc.leaves.entity.bot.action.CustomBotAction; -import org.leavesmc.leaves.entity.bot.actions.CraftCustomBotAction; - -public class ServerCustomBotAction extends AbstractBotAction { - private final CustomBotAction customBotAction; - - public ServerCustomBotAction(@NotNull CustomBotAction customBotAction) { - super(customBotAction.getName(), () -> new ServerCustomBotAction(customBotAction)); - this.customBotAction = customBotAction; - customBotAction.provideArgumentFactory(new LeavesWrappedArgument.ArgumentHandler() { - @Override - public LeavesWrappedArgument create(String name, ArgumentType type) { - return addArgument(name, type); - } - - @Override - public void fork(int forkId) { - ServerCustomBotAction.this.fork(forkId); - } - }); - customBotAction.init(); - } - - @Override - public String getActionDataString(@NotNull ExtraData data) { - customBotAction.provideActionData(data); - return super.getActionDataString(data); - } - - @Override - public void loadCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException { - super.loadCommand(context); - customBotAction.loadCommand(context.rawContext()); - } - - @Override - public boolean doTick(@NotNull ServerBot bot) { - return customBotAction.doTick(bot.getBukkitEntity()); - } - - @Override - public Object asCraft() { - return new CraftCustomBotAction(this); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index 0c499365..8333826d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -13,7 +13,7 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; public class ServerLookAction extends AbstractBotAction { @@ -31,7 +31,7 @@ public ServerLookAction() { } @Override - public void loadCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException { + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { PlayerSelectorArgumentResolver playerSelectorResolver = context.getArgumentOrDefault("player", PlayerSelectorArgumentResolver.class, null); FinePositionResolver positionResolver = context.getArgumentOrDefault("location", FinePositionResolver.class, null); CommandSourceStack source = context.getSource(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index a7a1509e..4023b469 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -2,8 +2,8 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.arguments.EnumArgumentType; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; @@ -18,7 +18,7 @@ public ServerMoveAction() { } @Override - public void loadCommand(@NotNull LeavesCommandContext context) { + public void loadCommand(@NotNull CommandContext context) { this.direction = context.getArgument("direction", MoveDirection.class); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 3be55610..85f51064 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -7,8 +7,8 @@ import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; import java.text.DecimalFormat; @@ -47,7 +47,7 @@ public ServerRotationAction() { private float pitch = 0.0f; @Override - public void loadCommand(@NotNull LeavesCommandContext context) { + public void loadCommand(@NotNull CommandContext context) { CommandSender sender = context.getSender(); if (sender instanceof Entity entity) { this.yaw = entity.getYaw(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java index 75f6a655..7b87332d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -9,8 +9,8 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.WrappedArgument; import java.lang.reflect.Method; @@ -34,7 +34,7 @@ public AbstractBotConfig(String name, ArgumentType type, Supplier creator) } @SuppressWarnings("RedundantThrows") - public void applySuggestions(final LeavesCommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { + public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { } public AbstractBotConfig setBot(ServerBot bot) { @@ -50,7 +50,7 @@ public E create() { public abstract void setValue(T value) throws CommandSyntaxException; - public abstract T loadFromCommand(@NotNull LeavesCommandContext context) throws CommandSyntaxException; + public abstract T loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; public String getName() { return name; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index 808d6d53..59ba3583 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.command.CommandContext; public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; @@ -25,7 +25,7 @@ public void setValue(Boolean value) { } @Override - public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { + public Boolean loadFromCommand(@NotNull CommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java index 017a4f2f..cfb94613 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java @@ -5,7 +5,7 @@ import net.minecraft.server.waypoints.ServerWaypointManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.command.CommandContext; public class LocatorBarConfig extends AbstractBotConfig { private boolean value; @@ -32,7 +32,7 @@ public void setValue(@NotNull Boolean value) throws IllegalArgumentException { } @Override - public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { + public Boolean loadFromCommand(@NotNull CommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 2451ad03..042064c7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -5,7 +5,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.command.CommandContext; import static net.minecraft.network.chat.Component.literal; @@ -16,7 +16,7 @@ public SimulationDistanceConfig() { } @Override - public void applySuggestions(LeavesCommandContext context, @NotNull SuggestionsBuilder builder) { + public void applySuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { builder.suggest("2", literal("Minimum simulation distance")); builder.suggest("8"); builder.suggest("12"); @@ -35,7 +35,7 @@ public void setValue(Integer value) { } @Override - public Integer loadFromCommand(@NotNull LeavesCommandContext context) { + public Integer loadFromCommand(@NotNull CommandContext context) { return context.getInteger(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index 9dbcb8fd..9580313a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.command.CommandContext; public class SkipSleepConfig extends AbstractBotConfig { @@ -23,7 +23,7 @@ public void setValue(Boolean value) throws IllegalArgumentException { } @Override - public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { + public Boolean loadFromCommand(@NotNull CommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index cd7dfbf4..f155beda 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -4,8 +4,8 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.util.ExtraData; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; @@ -32,7 +32,7 @@ public String getExtraDataString(@NotNull ExtraData data) { } @Override - public Boolean loadFromCommand(@NotNull LeavesCommandContext context) { + public Boolean loadFromCommand(@NotNull CommandContext context) { return context.getBoolean(getName()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index 6027e41a..f3fb34a7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesCommandContext; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.arguments.EnumArgumentType; public class TickTypeConfig extends AbstractBotConfig { @@ -16,7 +16,7 @@ public TickTypeConfig() { } @Override - public ServerBot.TickType loadFromCommand(@NotNull LeavesCommandContext context) { + public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) { return context.getArgument("tick_type", ServerBot.TickType.class); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java index 5d3a0a8f..21dee9f9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java @@ -14,7 +14,7 @@ import static org.leavesmc.leaves.command.CommandNode.getNameForNode; @SuppressWarnings({"ClassCanBeRecord", "unused"}) -public class CommandContext implements LeavesCommandContext { +public class CommandContext { private final com.mojang.brigadier.context.CommandContext source; public CommandContext(com.mojang.brigadier.context.CommandContext source) { @@ -119,7 +119,7 @@ public boolean isForked() { return source.isForked(); } - public com.mojang.brigadier.context.CommandContext rawContext() { + public com.mojang.brigadier.context.CommandContext getMojangContext() { return source; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java index b0f6e4a7..0c3326fb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java @@ -2,12 +2,15 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; import java.util.concurrent.CompletableFuture; -public class WrappedArgument implements LeavesWrappedArgument { +public class WrappedArgument { private final String name; private final ArgumentType type; private AsyncSuggestionProvider asyncSuggestionProvider = null; @@ -52,4 +55,14 @@ public RequiredArgumentBuilder compile() { } return builder; } + + @FunctionalInterface + public interface SuggestionApplier { + void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } + + @FunctionalInterface + public interface AsyncSuggestionProvider { + CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java index 99085738..d0736996 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -6,7 +6,6 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.command.bot.subcommands.action.ListCommand; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java index 70555b4d..3b0ae0cf 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -19,7 +19,6 @@ import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.event.bot.BotCreateEvent; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java index 77a85d9a..3464717d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java @@ -16,7 +16,6 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.List; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java index 6c8d942d..7a5e3481 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -13,7 +13,6 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.bot.BotSubcommand; import java.util.Set; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java index cf7b5056..f0dac9af 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -9,7 +9,6 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.arguments.BotArgumentType; import org.leavesmc.leaves.command.bot.BotSubcommand; import org.leavesmc.leaves.event.bot.BotRemoveEvent; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java index ea2d02cb..1547891e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java @@ -6,7 +6,6 @@ import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java index 8f9ea4d0..126c8ea2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -12,7 +12,6 @@ import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.WrappedArgument; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java index dc48f7b3..16d75583 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java @@ -11,7 +11,6 @@ import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; import org.leavesmc.leaves.event.bot.BotActionStopEvent; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java index a47e6cbd..86aa3a54 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java @@ -7,7 +7,6 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.LiteralNode; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java index bb5eeb1e..2d7505b2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -8,7 +8,6 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.command.ArgumentNode; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.CommandUtils; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import org.leavesmc.leaves.config.GlobalConfigManager; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java index 1867c983..bf4d4428 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java @@ -6,7 +6,6 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.command.CommandContext; -import org.leavesmc.leaves.command.LeavesCommandContext; import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import static net.kyori.adventure.text.Component.text; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java index 01bb157c..550985c4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java @@ -2,9 +2,7 @@ import com.google.common.collect.Lists; import net.minecraft.server.MinecraftServer; -import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.BotCreateState; @@ -13,7 +11,6 @@ import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; -import org.leavesmc.leaves.entity.bot.action.CustomBotAction; import org.leavesmc.leaves.event.bot.BotCreateEvent; import java.util.Collection; @@ -74,18 +71,4 @@ public > T newAction(@NotNull Class type) { public BotCreator botCreator(@NotNull String realName, @NotNull Location location) { return BotCreateState.builder(realName, location).createReason(BotCreateEvent.CreateReason.PLUGIN); } - - @Override - public boolean registerCustomAction(@NotNull CustomBotAction customBotAction, boolean resendCommandTree) { - boolean result = Actions.register(customBotAction); - if (result && resendCommandTree) { - Bukkit.getOnlinePlayers().forEach(Player::updateCommands); - } - return result; - } - - @Override - public boolean registerCustomAction(@NotNull CustomBotAction customBotAction) { - return registerCustomAction(customBotAction, true); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java deleted file mode 100644 index 730590db..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftCustomBotAction.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.leavesmc.leaves.entity.bot.actions; - -import org.leavesmc.leaves.bot.agent.actions.ServerCustomBotAction; -import org.leavesmc.leaves.entity.bot.action.CustomBotAction; - -public class CraftCustomBotAction extends CraftBotAction implements CustomBotAction.InternalCustomBotAction { - - public CraftCustomBotAction(ServerCustomBotAction serverAction) { - super(serverAction, CraftCustomBotAction::new); - } -} From bb8ac995ebf5b52dcbd3aac7bb9ee72a36bf76a6 Mon Sep 17 00:00:00 2001 From: MC_XiaoHei Date: Wed, 1 Oct 2025 15:47:59 +0800 Subject: [PATCH 29/29] chore: format --- .../command/bot/subcommands/RemoveCommand.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java index 67f75ad5..8a46649c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -115,15 +115,9 @@ private static int parseRemoveTime(String timeStr) throws CommandSyntaxException foundMatch = true; int value = Integer.parseInt(matcher.group(1)); switch (matcher.group(2).toLowerCase()) { - case "h": - seconds += value * 3600; - break; - case "m": - seconds += value * 60; - break; - case "s": - seconds += value; - break; + case "h" -> seconds += value * 3600; + case "m" -> seconds += value * 60; + case "s" -> seconds += value; } }