mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-29 20:09:23 +00:00
fix: fix bot action command
This commit is contained in:
@@ -59,12 +59,13 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
|
||||
|
||||
public abstract Object asCraft();
|
||||
|
||||
public List<Pair<String, String>> 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 abstract class ServerBotAction<E extends ServerBotAction<E>> {
|
||||
public void setOnStop(Consumer<E> onStop) {
|
||||
this.onStop = onStop;
|
||||
}
|
||||
|
||||
public record ActionData(
|
||||
List<Pair<String, String>> raw
|
||||
) {
|
||||
public void add(String key, String value) {
|
||||
raw.add(Pair.of(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,16 @@ public class ServerLookAction extends ServerBotAction<ServerLookAction> {
|
||||
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) {
|
||||
|
||||
@@ -22,8 +22,8 @@ public class ServerMountAction extends ServerBotAction<ServerMountAction> {
|
||||
Location center = bot.getBukkitEntity().getLocation();
|
||||
List<Vehicle> 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();
|
||||
|
||||
@@ -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.event.bot.BotActionStopEvent;
|
||||
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<ServerMoveAction> {
|
||||
|
||||
private static final Map<String, MoveDirection> 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 class ServerMoveAction extends ServerStateBotAction<ServerMoveAction> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provideActionData(@NotNull ActionData data) {
|
||||
super.provideActionData(data);
|
||||
data.add("direction", direction.name);
|
||||
}
|
||||
|
||||
public MoveDirection getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,13 @@ public class ServerRotationAction extends ServerBotAction<ServerRotationAction>
|
||||
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) {
|
||||
|
||||
@@ -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 abstract class ServerTimerBotAction<E extends ServerTimerBotAction<E>> ex
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<String, String>> 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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,13 @@ public abstract class ServerUseBotAction<T extends ServerUseBotAction<T>> extend
|
||||
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) {
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -52,13 +53,13 @@ public class CommandContext {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V, T> @NotNull V getCustomArgument(final Class<? extends CustomArgumentNode<V, T>> nodeClass) {
|
||||
public <V, T> @NotNull V getCustomArgument(final Class<? extends CustomArgumentNode<V, T>> nodeClass) throws CommandSyntaxException {
|
||||
String name = getNameForNode(nodeClass);
|
||||
T raw = (T) source.getArgument(name, Object.class);
|
||||
return CustomArgumentNode.transform(nodeClass, raw);
|
||||
}
|
||||
|
||||
public <V> @NotNull V getArgumentOrDefault(final Class<? extends ArgumentNode<V>> nodeClass, final V defaultValue) {
|
||||
public <V> V getArgumentOrDefault(final Class<? extends ArgumentNode<V>> nodeClass, final V defaultValue) {
|
||||
try {
|
||||
return getArgument(nodeClass);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@@ -74,7 +75,7 @@ public class CommandContext {
|
||||
}
|
||||
}
|
||||
|
||||
public <V, T> V getCustomArgumentOrDefault(final Class<? extends CustomArgumentNode<V, T>> nodeClass, final V defaultValue) {
|
||||
public <V, T> V getCustomArgumentOrDefault(final Class<? extends CustomArgumentNode<V, T>> nodeClass, final V defaultValue) throws CommandSyntaxException {
|
||||
try {
|
||||
return getCustomArgument(nodeClass);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@@ -121,4 +122,8 @@ public class CommandContext {
|
||||
public boolean isForked() {
|
||||
return source.isForked();
|
||||
}
|
||||
|
||||
public com.mojang.brigadier.context.CommandContext<CommandSourceStack> getMojangContext() {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 @@ public abstract class CommandNode {
|
||||
|
||||
protected abstract ArgumentBuilder<CommandSourceStack, ?> compileBase();
|
||||
|
||||
protected boolean execute(CommandContext context) {
|
||||
protected boolean execute(CommandContext context) throws CommandSyntaxException {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.leavesmc.leaves.neo_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;
|
||||
|
||||
@@ -17,7 +18,7 @@ public class CustomArgumentNode<T, B> extends ArgumentNode<B> {
|
||||
TYPES.put(getClass(), argumentType);
|
||||
}
|
||||
|
||||
public static <T, B> T transform(Class<? extends CustomArgumentNode<T, B>> nodeClass, B base) {
|
||||
public static <T, B> T transform(Class<? extends CustomArgumentNode<T, B>> nodeClass, B base) throws CommandSyntaxException {
|
||||
@SuppressWarnings("unchecked")
|
||||
CustomArgumentType<T, B> type = (CustomArgumentType<T, B>) TYPES.get(nodeClass);
|
||||
if (type == null) {
|
||||
|
||||
@@ -11,7 +11,7 @@ public interface CustomArgumentType<T, B> {
|
||||
|
||||
ArgumentType<B> getBaseArgumentType();
|
||||
|
||||
T transform(B value);
|
||||
T transform(B value) throws CommandSyntaxException;
|
||||
|
||||
CompletableFuture<Suggestions> getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ package org.leavesmc.leaves.neo_command.bot;
|
||||
|
||||
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 class BotArgument implements CustomArgumentType<ServerBot, String> {
|
||||
}
|
||||
|
||||
@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<Suggestions> getSuggestions(CommandContext context, SuggestionsBuilder builder) {
|
||||
public CompletableFuture<Suggestions> getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException {
|
||||
Collection<Bot> bots = Bukkit.getBotManager().getBots();
|
||||
if (bots.isEmpty()) {
|
||||
return builder
|
||||
|
||||
@@ -6,6 +6,8 @@ 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;
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@ public class ActionCommand extends LiteralNode {
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String> {
|
||||
|
||||
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<String> {
|
||||
|
||||
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<ResourceLocation> {
|
||||
|
||||
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<Coordinates> {
|
||||
|
||||
public LocationArgument() {
|
||||
super("location", Vec3Argument.vec3(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(CommandContext context) throws CommandSyntaxException {
|
||||
return handleCreateCommand(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<ServerBot> 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<ResourceLocation> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 org.leavesmc.leaves.neo_command.bot.subcommands.ActionCommand;
|
||||
|
||||
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 class ListCommand extends LiteralNode {
|
||||
}
|
||||
|
||||
@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<ServerBotAction<?>> 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())))
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -38,21 +38,20 @@ public class StartCommand extends LiteralNode {
|
||||
.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 @@ public class StartCommand extends LiteralNode {
|
||||
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
|
||||
ArgumentBuilder<CommandSourceStack, ?> builder = super.compile();
|
||||
|
||||
for (Map.Entry<Integer, List<Pair<String, WrappedArgument<?>>>> entry : action.getArguments().entrySet()) {
|
||||
Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments = action.getArguments();
|
||||
Command<CommandSourceStack> executor = context -> {
|
||||
if (handleStartCommand(new CommandContext(context), action)) {
|
||||
return Command.SINGLE_SUCCESS;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
for (Map.Entry<Integer, List<Pair<String, WrappedArgument<?>>>> entry : arguments.entrySet()) {
|
||||
List<Pair<String, WrappedArgument<?>>> value = entry.getValue();
|
||||
ArgumentBuilder<CommandSourceStack, ?> branchArgumentBuilder = null;
|
||||
Command<CommandSourceStack> executor = context -> {
|
||||
if (executor(new CommandContext(context), action)) {
|
||||
return Command.SINGLE_SUCCESS;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
for (Pair<String, WrappedArgument<?>> stringWrappedArgumentPair : value.reversed()) {
|
||||
WrappedArgument<?> argument = stringWrappedArgumentPair.getRight();
|
||||
@@ -86,7 +86,7 @@ public class StartCommand extends LiteralNode {
|
||||
}
|
||||
}
|
||||
|
||||
if (value.getFirst().getRight().isOptional()) {
|
||||
if (value.getFirst().getRight().isOptional() || value.isEmpty()) {
|
||||
builder = builder.executes(executor);
|
||||
}
|
||||
|
||||
@@ -94,6 +94,11 @@ public class StartCommand extends LiteralNode {
|
||||
builder = builder.then(branchArgumentBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.isEmpty()) {
|
||||
builder = builder.executes(executor);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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.LiteralNode;
|
||||
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 @@ public class StopCommand extends LiteralNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<Suggestions> getSuggestions(CommandContext context, SuggestionsBuilder builder) {
|
||||
protected CompletableFuture<Suggestions> 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 @@ public class StopCommand extends LiteralNode {
|
||||
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 class StopCommand extends LiteralNode {
|
||||
}
|
||||
|
||||
@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<ServerBotAction<?>> actions = bot.getBotActions();
|
||||
CommandSender sender = context.getSender();
|
||||
if (actions.isEmpty()) {
|
||||
sender.sendMessage(text("This bot has no active actions", GRAY));
|
||||
return true;
|
||||
}
|
||||
|
||||
Set<ServerBotAction<?>> canceled = new HashSet<>();
|
||||
Set<ServerBotAction<?>> 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 @@ public class StopCommand extends LiteralNode {
|
||||
}
|
||||
}
|
||||
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())))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user