9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-29 11:59:17 +00:00

feat: add bot config command

This commit is contained in:
MC_XiaoHei
2025-08-24 10:11:31 +08:00
parent eb86035885
commit 67e128db95
48 changed files with 573 additions and 423 deletions

View File

@@ -2,7 +2,6 @@ package org.leavesmc.leaves.bot;
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());

View File

@@ -59,10 +59,10 @@ 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.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 @@ import java.util.function.Predicate;
public class ServerBot extends ServerPlayer {
private final List<ServerBotAction<?>> actions;
private final Map<Configs<?>, AbstractBotConfig<?>> configs;
private final List<AbstractBotAction<?>> actions;
private final Map<String, AbstractBotConfig<?, ?, ?>> configs;
public boolean resume = false;
public BotCreateState createState;
@@ -106,9 +106,9 @@ public class ServerBot extends ServerPlayer {
this.gameMode = new ServerBotGameMode(this);
this.actions = new ArrayList<>();
ImmutableMap.Builder<Configs<?>, AbstractBotConfig<?>> configBuilder = ImmutableMap.builder();
for (Configs<?> config : Configs.getConfigs()) {
configBuilder.put(config, config.createConfig(this));
ImmutableMap.Builder<String, AbstractBotConfig<?, ?, ?>> 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 class ServerBot extends ServerPlayer {
if (!this.actions.isEmpty()) {
ValueOutput.TypedOutputList<CompoundTag> 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<CompoundTag> 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 class ServerBot extends ServerPlayer {
if (nbt.list("actions", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> 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 class ServerBot extends ServerPlayer {
if (nbt.list("configs", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> 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 class ServerBot extends ServerPlayer {
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 class ServerBot extends ServerPlayer {
return true;
}
public List<ServerBotAction<?>> getBotActions() {
public List<AbstractBotAction<?>> getBotActions() {
return actions;
}
@@ -669,11 +669,11 @@ public class ServerBot extends ServerPlayer {
}
@SuppressWarnings("unchecked")
public <E> AbstractBotConfig<E> getConfig(Configs<E> config) {
return (AbstractBotConfig<E>) Objects.requireNonNull(this.configs.get(config));
public <O, I, E extends AbstractBotConfig<O, I, E>> AbstractBotConfig<O, I, E> getConfig(@NotNull AbstractBotConfig<O, I, E> config) {
return (AbstractBotConfig<O, I, E>) Objects.requireNonNull(this.configs.get(config.getName()));
}
public <E> E getConfigValue(Configs<E> config) {
public <O, I, E extends AbstractBotConfig<O, I, E>> O getConfigValue(@NotNull AbstractBotConfig<O, I, E> config) {
return this.getConfig(config).getValue();
}

View File

@@ -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<E> {
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<E> 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<String> getMessage() {
return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + ": " + this.getValue());
}
public List<String> 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);
}

View File

@@ -13,8 +13,8 @@ import java.util.Set;
public class Actions {
private static final Map<String, ServerBotAction<?>> actionsByName = new HashMap<>();
private static final Map<Class<?>, ServerBotAction<?>> actionsByClass = new HashMap<>();
private static final Map<String, AbstractBotAction<?>> actionsByName = new HashMap<>();
private static final Map<Class<?>, AbstractBotAction<?>> actionsByClass = new HashMap<>();
public static void registerAll() {
register(new ServerAttackAction(), AttackAction.class);
@@ -38,7 +38,7 @@ public class Actions {
register(new ServerSwapAction(), SwapAction.class);
}
public static boolean register(@NotNull ServerBotAction<?> action, Class<? extends BotAction<?>> type) {
public static boolean register(@NotNull AbstractBotAction<?> action, Class<? extends BotAction<?>> type) {
if (!actionsByName.containsKey(action.getName())) {
actionsByName.put(action.getName(), action);
actionsByClass.put(type, action);
@@ -54,7 +54,7 @@ public class Actions {
@NotNull
@Contract(pure = true)
public static Collection<ServerBotAction<?>> getAll() {
public static Collection<AbstractBotAction<?>> getAll() {
return actionsByName.values();
}
@@ -64,12 +64,12 @@ public class Actions {
}
@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);
}
}

View File

@@ -3,7 +3,7 @@ package org.leavesmc.leaves.bot.agent;
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 org.leavesmc.leaves.bot.agent.configs.TickTypeConfig;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
@SuppressWarnings("unused")
public class Configs<E> {
@SuppressWarnings({"unused"})
public class Configs {
private static final Map<Class<?>, AbstractBotConfig<?, ?, ?>> configs = new HashMap<>();
private static final Map<String, Configs<?>> configs = new HashMap<>();
public static final Configs<Boolean> SKIP_SLEEP = register(SkipSleepConfig.class, SkipSleepConfig::new);
public static final Configs<Boolean> ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new);
public static final Configs<Boolean> SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new);
public static final Configs<Integer> SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new);
public static final Configs<ServerBot.TickType> TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new);
public static final Configs<Boolean> ENABLE_LOCATOR_BAR = register(LocatorBarConfig.class, LocatorBarConfig::new);
private final Class<? extends AbstractBotConfig<E>> configClass;
private final Supplier<? extends AbstractBotConfig<E>> configCreator;
private Configs(Class<? extends AbstractBotConfig<E>> configClass, Supplier<? extends AbstractBotConfig<E>> configCreator) {
this.configClass = configClass;
this.configCreator = configCreator;
}
public Class<? extends AbstractBotConfig<E>> getConfigClass() {
return configClass;
}
public AbstractBotConfig<E> 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<Configs<?>> getConfigs() {
public static Collection<AbstractBotConfig<?, ?, ?>> getConfigs() {
return configs.values();
}
@NotNull
@Contract(pure = true)
public static Collection<String> getConfigNames() {
return configs.keySet();
}
@NotNull
private static <E> Configs<E> register(Class<? extends AbstractBotConfig<E>> configClass, Supplier<? extends AbstractBotConfig<E>> configCreator) {
Configs<E> config = new Configs<>(configClass, configCreator);
configs.put(config.createConfig(null).getName(), config);
return config;
@SuppressWarnings("unchecked")
private static <O, I, E extends AbstractBotConfig<O, I, E>> @NotNull E register(AbstractBotConfig<O, I, E> instance) {
configs.put(instance.getClass(), instance);
return (E) instance;
}
}

View File

@@ -23,7 +23,7 @@ import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class ServerBotAction<E extends ServerBotAction<E>> {
public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
private final String name;
private final Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments;
@@ -43,7 +43,7 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
private Consumer<E> onSuccess;
private Consumer<E> onStop;
public ServerBotAction(String name, Supplier<E> creator) {
public AbstractBotAction(String name, Supplier<E> creator) {
this.name = name;
this.uuid = UUID.randomUUID();
this.creator = creator;

View File

@@ -0,0 +1,11 @@
package org.leavesmc.leaves.bot.agent.actions;
import java.util.function.Supplier;
public abstract class AbstractStateBotAction<E extends AbstractStateBotAction<E>> extends AbstractBotAction<E> {
public AbstractStateBotAction(String name, Supplier<E> creator) {
super(name, creator);
this.setDoNumber(-1);
}
}

View File

@@ -9,9 +9,9 @@ import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings;
public abstract class ServerTimerBotAction<E extends ServerTimerBotAction<E>> extends ServerBotAction<E> {
public abstract class AbstractTimerBotAction<E extends AbstractTimerBotAction<E>> extends AbstractBotAction<E> {
public ServerTimerBotAction(String name, Supplier<E> creator) {
public AbstractTimerBotAction(String name, Supplier<E> creator) {
super(name, creator);
this.addArgument("delay", integer(0))
.suggests(strings("0", "5", "10", "20"))

View File

@@ -12,12 +12,12 @@ import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
public abstract class ServerUseBotAction<T extends ServerUseBotAction<T>> extends ServerTimerBotAction<T> {
public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> extends AbstractTimerBotAction<T> {
private int useTickTimeout = -1;
private int alreadyUsedTick = 0;
private int useItemRemainingTicks = 0;
public ServerUseBotAction(String name, Supplier<T> supplier) {
public AbstractUseBotAction(String name, Supplier<T> supplier) {
super(name, supplier);
this.addArgument("use_timeout", integer(-1))
.suggests((context, builder) -> {

View File

@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftAttackAction;
public class ServerAttackAction extends ServerTimerBotAction<ServerAttackAction> {
public class ServerAttackAction extends AbstractTimerBotAction<ServerAttackAction> {
public ServerAttackAction() {
super("attack", ServerAttackAction::new);

View File

@@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBreakBlockAction;
public class ServerBreakBlockAction extends ServerTimerBotAction<ServerBreakBlockAction> {
public class ServerBreakBlockAction extends AbstractTimerBotAction<ServerBreakBlockAction> {
public ServerBreakBlockAction() {
super("break", ServerBreakBlockAction::new);

View File

@@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftDropAction;
public class ServerDropAction extends ServerTimerBotAction<ServerDropAction> {
public class ServerDropAction extends AbstractTimerBotAction<ServerDropAction> {
public ServerDropAction() {
super("drop", ServerDropAction::new);

View File

@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftFishAction;
public class ServerFishAction extends ServerTimerBotAction<ServerFishAction> {
public class ServerFishAction extends AbstractTimerBotAction<ServerFishAction> {
public ServerFishAction() {
super("fish", ServerFishAction::new);

View File

@@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftJumpAction;
public class ServerJumpAction extends ServerTimerBotAction<ServerJumpAction> {
public class ServerJumpAction extends AbstractTimerBotAction<ServerJumpAction> {
public ServerJumpAction() {
super("jump", ServerJumpAction::new);

View File

@@ -16,7 +16,7 @@ import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftLookAction;
import org.leavesmc.leaves.neo_command.CommandContext;
public class ServerLookAction extends ServerBotAction<ServerLookAction> {
public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
private static final Vector ZERO_VECTOR = new Vector(0, 0, 0);

View File

@@ -11,7 +11,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftMountAction;
import java.util.Comparator;
import java.util.List;
public class ServerMountAction extends ServerBotAction<ServerMountAction> {
public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
public ServerMountAction() {
super("mount", ServerMountAction::new);

View File

@@ -15,7 +15,7 @@ import java.util.Map;
import static java.util.stream.Collectors.toMap;
import static org.leavesmc.leaves.neo_command.ArgumentNode.ArgumentSuggestions.strings;
public class ServerMoveAction extends ServerStateBotAction<ServerMoveAction> {
public class ServerMoveAction extends AbstractStateBotAction<ServerMoveAction> {
private static final Map<String, MoveDirection> NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap(
it -> it.name,
it -> it

View File

@@ -11,7 +11,7 @@ import org.leavesmc.leaves.neo_command.CommandContext;
import java.text.DecimalFormat;
public class ServerRotationAction extends ServerBotAction<ServerRotationAction> {
public class ServerRotationAction extends AbstractBotAction<ServerRotationAction> {
private static final DecimalFormat DF = new DecimalFormat("0.00");

View File

@@ -5,7 +5,7 @@ import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
public class ServerSneakAction extends ServerStateBotAction<ServerSneakAction> {
public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction> {
public ServerSneakAction() {
super("sneak", ServerSneakAction::new);

View File

@@ -1,11 +0,0 @@
package org.leavesmc.leaves.bot.agent.actions;
import java.util.function.Supplier;
public abstract class ServerStateBotAction<E extends ServerStateBotAction<E>> extends ServerBotAction<E> {
public ServerStateBotAction(String name, Supplier<E> creator) {
super(name, creator);
this.setDoNumber(-1);
}
}

View File

@@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction;
public class ServerSwapAction extends ServerBotAction<ServerSwapAction> {
public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
public ServerSwapAction() {
super("swap", ServerSwapAction::new);

View File

@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction;
public class ServerSwimAction extends ServerStateBotAction<ServerSwimAction> {
public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
public ServerSwimAction() {
super("swim", ServerSwimAction::new);

View File

@@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction;
public class ServerUseItemAction extends ServerUseBotAction<ServerUseItemAction> {
public class ServerUseItemAction extends AbstractUseBotAction<ServerUseItemAction> {
public ServerUseItemAction() {
super("use", ServerUseItemAction::new);

View File

@@ -17,7 +17,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
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<ServerUseItemAutoAction> {
public class ServerUseItemAutoAction extends AbstractUseBotAction<ServerUseItemAutoAction> {
public ServerUseItemAutoAction() {
super("use_auto", ServerUseItemAutoAction::new);

View File

@@ -7,7 +7,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
public class ServerUseItemOffhandAction extends ServerUseBotAction<ServerUseItemOffhandAction> {
public class ServerUseItemOffhandAction extends AbstractUseBotAction<ServerUseItemOffhandAction> {
public ServerUseItemOffhandAction() {
super("use_offhand", ServerUseItemOffhandAction::new);

View File

@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction;
public class ServerUseItemOnAction extends ServerUseBotAction<ServerUseItemOnAction> {
public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnAction> {
public ServerUseItemOnAction() {
super("use_on", ServerUseItemOnAction::new);

View File

@@ -8,7 +8,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
public class ServerUseItemOnOffhandAction extends ServerUseBotAction<ServerUseItemOnOffhandAction> {
public class ServerUseItemOnOffhandAction extends AbstractUseBotAction<ServerUseItemOnOffhandAction> {
public ServerUseItemOnOffhandAction() {
super("use_on_offhand", ServerUseItemOnOffhandAction::new);

View File

@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction;
public class ServerUseItemToAction extends ServerUseBotAction<ServerUseItemToAction> {
public class ServerUseItemToAction extends AbstractUseBotAction<ServerUseItemToAction> {
public ServerUseItemToAction() {
super("use_to", ServerUseItemToAction::new);

View File

@@ -8,7 +8,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo;
public class ServerUseItemToOffhandAction extends ServerUseBotAction<ServerUseItemToOffhandAction> {
public class ServerUseItemToOffhandAction extends AbstractUseBotAction<ServerUseItemToOffhandAction> {
public ServerUseItemToOffhandAction() {
super("use_to_offhand", ServerUseItemToOffhandAction::new);

View File

@@ -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<O, I, E extends AbstractBotConfig<O, I, E>> {
private final String name;
private final WrappedArgument<I> argument;
private final Supplier<E> creator;
protected ServerBot bot;
public AbstractBotConfig(String name, ArgumentType<I> type, Supplier<E> 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<O, I, E> 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<Pair<String, String>> 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<I> 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;
}
}

View File

@@ -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<Boolean> {
public static final String NAME = "always_send_data";
import org.leavesmc.leaves.neo_command.CommandContext;
public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean, Boolean, AlwaysSendDataConfig> {
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 class AlwaysSendDataConfig extends AbstractBotConfig<Boolean> {
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));
}
}

View File

@@ -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<Boolean> {
public static final String NAME = "enable_locator_bar";
import org.leavesmc.leaves.neo_command.CommandContext;
public class LocatorBarConfig extends AbstractBotConfig<Boolean, Boolean, LocatorBarConfig> {
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 class LocatorBarConfig extends AbstractBotConfig<Boolean> {
}
@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 class LocatorBarConfig extends AbstractBotConfig<Boolean> {
}
}
@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));
}
}

View File

@@ -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<Integer> {
public static final String NAME = "simulation_distance";
public class SimulationDistanceConfig extends AbstractBotConfig<Integer, Integer, SimulationDistanceConfig> {
public SimulationDistanceConfig() {
super(NAME, CommandArgument.of(CommandArgumentType.INTEGER).setSuggestion(0, Pair.of(List.of("2", "10"), "<INT 2 - 32>")));
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 class SimulationDistanceConfig extends AbstractBotConfig<Integer> {
@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)));
}
}

View File

@@ -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<Boolean> {
public static final String NAME = "skip_sleep";
public class SkipSleepConfig extends AbstractBotConfig<Boolean, Boolean, SkipSleepConfig> {
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 class SkipSleepConfig extends AbstractBotConfig<Boolean> {
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));
}
}

View File

@@ -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<Boolean> {
public static final String NAME = "spawn_phantom";
public class SpawnPhantomConfig extends AbstractBotConfig<Boolean, Boolean, SpawnPhantomConfig> {
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 class SpawnPhantomConfig extends AbstractBotConfig<Boolean> {
}
@Override
public List<String> getMessage() {
return List.of(
bot.getScoreboardName() + "'s spawn_phantom: " + this.getValue(),
bot.getScoreboardName() + "'s not_sleeping_ticks: " + bot.notSleepTicks
);
public List<Pair<String, String>> 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));
}
}

View File

@@ -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<ServerBot.TickType> {
private static final String NAME = "tick_type";
private static final CommandArgumentType<ServerBot.TickType> TICK_TYPE_ARGUMENT = CommandArgumentType.ofEnum(ServerBot.TickType.class);
import org.leavesmc.leaves.neo_command.CommandContext;
public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType, String, TickTypeConfig> {
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 class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType> {
@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);
});
}
}

View File

@@ -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 <name> <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<List<String>, 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 <name> <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<List<String>, 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;
// }
//}

View File

@@ -9,7 +9,7 @@ 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.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 class CraftBot extends CraftPlayer implements Bot {
@Override
public void stopAllActions() {
for (ServerBotAction<?> action : this.getHandle().getBotActions()) {
for (AbstractBotAction<?> action : this.getHandle().getBotActions()) {
action.stop(this.getHandle(), BotActionStopEvent.Reason.PLUGIN);
}
}

View File

@@ -9,7 +9,7 @@ import org.leavesmc.leaves.bot.BotCreateState;
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 class CraftBotManager implements BotManager {
@SuppressWarnings("unchecked")
@Override
public <T extends BotAction<T>> T newAction(@NotNull Class<T> 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 {

View File

@@ -2,14 +2,14 @@ package org.leavesmc.leaves.entity.bot.actions;
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<T extends BotAction<T>, S extends ServerBotAction<S>> implements BotAction<T> {
public abstract class CraftBotAction<T extends BotAction<T>, S extends AbstractBotAction<S>> implements BotAction<T> {
protected final S serverAction;
protected final Function<S, T> creator;
@@ -23,7 +23,7 @@ public abstract class CraftBotAction<T extends BotAction<T>, S extends ServerBot
this.creator = creator;
}
public ServerBotAction<?> getHandle() {
public AbstractBotAction<?> getHandle() {
return serverAction;
}

View File

@@ -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<T extends TimerBotAction<T>, S extends ServerTimerBotAction<S>> extends CraftBotAction<T, S> implements TimerBotAction<T> {
public class CraftTimerBotAction<T extends TimerBotAction<T>, S extends AbstractTimerBotAction<S>> extends CraftBotAction<T, S> implements TimerBotAction<T> {
public CraftTimerBotAction(S serverAction, Function<S, T> creator) {
super(serverAction, creator);

View File

@@ -46,6 +46,18 @@ public class CommandContext {
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 <V> @NotNull V getArgument(final Class<? extends ArgumentNode<V>> nodeClass) {
String name = getNameForNode(nodeClass);

View File

@@ -16,7 +16,7 @@ public class ActionCommand extends BotSubcommand {
public ActionCommand() {
super("action");
children(ActionCommand.BotArgument::new);
children(BotArgument::new);
}
@Override

View File

@@ -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<ServerBot, String> {
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<LiteralNode> 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<O> extends LiteralNode {
private final AbstractBotConfig<O, ?, ?> config;
private ConfigNode(@NotNull AbstractBotConfig<O, ?, ?> config) {
super(config.getName());
this.config = config;
}
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compileBase() {
RequiredArgumentBuilder<CommandSourceStack, ?> 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<O, ?, ?> 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<O, ?, ?> 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;
}
}
}

View File

@@ -4,7 +4,7 @@ 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;
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 @@ public class ListCommand extends LiteralNode {
ServerBot bot = ActionCommand.BotArgument.getBot(context);
CommandSender sender = context.getSender();
List<ServerBotAction<?>> actions = bot.getBotActions();
List<AbstractBotAction<?>> actions = bot.getBotActions();
if (actions.isEmpty()) {
sender.sendMessage(text("This bot has no active actions", GRAY));
return true;
@@ -41,7 +41,7 @@ public class ListCommand extends LiteralNode {
.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())))

View File

@@ -10,7 +10,7 @@ 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.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 class StartCommand extends LiteralNode {
.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 @@ public class StartCommand extends LiteralNode {
}
@Contract(pure = true)
private @NotNull Supplier<LiteralNode> actionNodeCreator(ServerBotAction<?> action) {
return () -> new LiteralNode(action.getName()) {
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
ArgumentBuilder<CommandSourceStack, ?> builder = super.compile();
private @NotNull Supplier<LiteralNode> actionNodeCreator(AbstractBotAction<?> action) {
return () -> new ActionLiteralNode(action);
}
Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments = action.getArguments();
Command<CommandSourceStack> executor = context -> {
if (handleStartCommand(new CommandContext(context), action)) {
return Command.SINGLE_SUCCESS;
private class ActionLiteralNode extends LiteralNode {
private final AbstractBotAction<?> action;
public ActionLiteralNode(@NotNull AbstractBotAction<?> action) {
super(action.getName());
this.action = action;
}
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
ArgumentBuilder<CommandSourceStack, ?> builder = super.compile();
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;
for (Pair<String, WrappedArgument<?>> stringWrappedArgumentPair : value.reversed()) {
WrappedArgument<?> argument = stringWrappedArgumentPair.getRight();
if (branchArgumentBuilder == null) {
branchArgumentBuilder = argument.compile().executes(executor);
} 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;
for (Pair<String, WrappedArgument<?>> 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);
}
branchArgumentBuilder = argument.compile().then(branchArgumentBuilder);
if (argument.isOptional()) {
branchArgumentBuilder = branchArgumentBuilder.executes(executor);
}
}
if (value.getFirst().getRight().isOptional() || value.isEmpty()) {
builder = builder.executes(executor);
}
if (branchArgumentBuilder != null) {
builder = builder.then(branchArgumentBuilder);
}
}
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;
}
}
}

View File

@@ -8,7 +8,7 @@ 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.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 @@ public class StopCommand extends LiteralNode {
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 @@ public class StopCommand extends LiteralNode {
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 class StopCommand extends LiteralNode {
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
ServerBot bot = ActionCommand.BotArgument.getBot(context);
List<ServerBotAction<?>> actions = bot.getBotActions();
List<AbstractBotAction<?>> 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 (ServerBotAction<?> action : actions) {
Set<AbstractBotAction<?>> canceled = new HashSet<>();
Set<AbstractBotAction<?>> 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 @@ public class StopCommand extends LiteralNode {
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())))
);

View File

@@ -48,9 +48,9 @@ public class ConfigCommand extends LiteralNode {
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();
}