Fake Player command use brigadier (#57)
* pre update for new command system branch * update ref
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ mcVersion=1.21.8
|
||||
release=2
|
||||
# 0 for skip release, 1 for pre-release, 2 for release
|
||||
|
||||
luminolRef=e7176d188b9e4d3b1f258d56cda91e2d008282f4
|
||||
luminolRef=a2af823b646334cdc64abb32b859f394c55ce0cc
|
||||
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.caching=true
|
||||
|
||||
@@ -5,10 +5,10 @@ Subject: [PATCH] Rebrand to Lophine
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index 4be82092886728b7862b6e8951cf1c8ab917ca55..1b822e9576573c360b997e5cb4fa02278c88b74f 100644
|
||||
index 5e341cdc1c6ff75552140ab16bc9ccd237d896d0..a780214137d10f2faa92042b2f32c77a6598fa8d 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -21,6 +21,7 @@ public class ConfigManager {
|
||||
@@ -22,6 +22,7 @@ public class ConfigManager {
|
||||
|
||||
public static void initConfigs() {
|
||||
configfiles.put("luminol", ConfigsInstance.of(new File("luminol_config"), "luminol", "me.earthme.luminol.config.modules"));
|
||||
|
||||
+16
-15
@@ -5,14 +5,10 @@ import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.leavesmc.leaves.bot.BotCommand;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.bot.agent.Actions;
|
||||
import org.leavesmc.leaves.command.bot.BotCommand;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "fakeplayer")
|
||||
public class FakeplayerConfig implements IConfigModule {
|
||||
@@ -86,23 +82,28 @@ public class FakeplayerConfig implements IConfigModule {
|
||||
|
||||
public static ServerBot.TickType tickType = ServerBot.TickType.ENTITY_LIST;
|
||||
|
||||
public static void unregisterCommand(String name) {
|
||||
name = name.toLowerCase(Locale.ENGLISH).trim();
|
||||
MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove(name);
|
||||
MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove("leaves:" + name);
|
||||
MinecraftServer.getServer().server.syncCommands();
|
||||
}
|
||||
private BotCommand command = null;
|
||||
|
||||
private boolean registered = false;
|
||||
|
||||
public static int getSimulationDistance(ServerBot bot) {
|
||||
return simulationDistance == -1 ? bot.getBukkitEntity().getSimulationDistance() : simulationDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaded(CommentedFileConfig configInstance) {
|
||||
if (enable) {
|
||||
Bukkit.getCommandMap().register("bot", "lophine", new BotCommand());
|
||||
Actions.registerAll();
|
||||
} else {
|
||||
unregisterCommand("bot");
|
||||
command = new BotCommand();
|
||||
command.register();
|
||||
registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnloaded(CommentedFileConfig configInstance) {
|
||||
if (registered) {
|
||||
command.unregister();
|
||||
command = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,504 +0,0 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.bot;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
|
||||
import org.leavesmc.leaves.event.bot.BotConfigModifyEvent;
|
||||
import org.leavesmc.leaves.event.bot.BotCreateEvent;
|
||||
import org.leavesmc.leaves.event.bot.BotRemoveEvent;
|
||||
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
public class BotCommand extends Command {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public BotCommand() {
|
||||
super("bot");
|
||||
this.setPermission("lophine.bot");
|
||||
this.setDescription("FakePlayer Command");
|
||||
this.setUsage("/bot <create|remove|list|action|config|save|load> [args...]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
||||
if (!testPermission(sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!FakeplayerConfig.enable) {
|
||||
sender.sendMessage(Component.text("Fakeplayer feature is disabled!").color(TextColor.color(255, 0, 0)));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage(Component.text("Usage: /bot <create|remove|list|action|config|save|load> [args...]").color(TextColor.color(255, 255, 0)));
|
||||
return true;
|
||||
}
|
||||
|
||||
String subCommand = args[0].toLowerCase();
|
||||
switch (subCommand) {
|
||||
case "create" -> {
|
||||
return handleCreate(sender, args);
|
||||
}
|
||||
case "remove" -> {
|
||||
return handleRemove(sender, args);
|
||||
}
|
||||
case "list" -> {
|
||||
return handleList(sender, args);
|
||||
}
|
||||
case "action" -> {
|
||||
return handleAction(sender, args);
|
||||
}
|
||||
case "config" -> {
|
||||
return handleConfig(sender, args);
|
||||
}
|
||||
case "save" -> {
|
||||
return handleSave(sender, args);
|
||||
}
|
||||
case "load" -> {
|
||||
return handleLoad(sender, args);
|
||||
}
|
||||
default -> {
|
||||
sender.sendMessage(Component.text("Unknown subcommand: " + subCommand).color(TextColor.color(255, 0, 0)));
|
||||
sender.sendMessage(Component.text("Available commands: create, remove, list, action, config, save, load").color(TextColor.color(255, 255, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleCreate(CommandSender sender, String[] args) {
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(text("Use /bot create <name> [skin_name] to create a fakeplayer", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
String botName = args[1];
|
||||
String fullName = BotUtil.getFullName(botName);
|
||||
if (this.canCreate(sender, fullName)) {
|
||||
BotCreateState.Builder builder = BotCreateState.builder(botName, Bukkit.getWorlds().getFirst().getSpawnLocation())
|
||||
.createReason(BotCreateEvent.CreateReason.COMMAND)
|
||||
.creator(sender);
|
||||
|
||||
if (args.length >= 3) {
|
||||
builder.skinName(args[2]);
|
||||
}
|
||||
|
||||
if (sender instanceof Player player) {
|
||||
builder.location(player.getLocation());
|
||||
} else if (sender instanceof ConsoleCommandSender) {
|
||||
if (args.length >= 7) {
|
||||
try {
|
||||
World world = Bukkit.getWorld(args[3]);
|
||||
double x = Double.parseDouble(args[4]);
|
||||
double y = Double.parseDouble(args[5]);
|
||||
double z = Double.parseDouble(args[6]);
|
||||
if (world != null) {
|
||||
builder.location(new Location(world, x, y, z));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Can't build location", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.spawnWithSkin(null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleRemove(CommandSender sender, String[] args) {
|
||||
if (args.length < 2 || args.length > 5) {
|
||||
sender.sendMessage(text("Usage: /bot remove <name> [hour] [minute] [second]", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
String botName = args[1];
|
||||
BotList botList = BotList.INSTANCE;
|
||||
ServerBot bot = botList.getBotByName(BotUtil.getFullName(botName));
|
||||
|
||||
if (bot == null) {
|
||||
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 3 && args[2].equals("cancel")) {
|
||||
if (bot.removeTaskId == -1) {
|
||||
sender.sendMessage(text("This fakeplayer is not scheduled to be removed", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
|
||||
bot.removeTaskId = -1;
|
||||
sender.sendMessage(text("Remove cancel"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
long time = 0;
|
||||
int h;
|
||||
long s = 0;
|
||||
long m = 0;
|
||||
|
||||
try {
|
||||
h = Integer.parseInt(args[2]);
|
||||
if (h < 0) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
time += ((long) h) * 3600 * 20;
|
||||
if (args.length > 3) {
|
||||
m = Long.parseLong(args[3]);
|
||||
if (m > 59 || m < 0) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
time += m * 60 * 20;
|
||||
}
|
||||
if (args.length > 4) {
|
||||
s = Long.parseLong(args[4]);
|
||||
if (s > 59 || s < 0) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
time += s * 20;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(text("Usage: /bot remove <name> [hour] [minute] [second]", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isReschedule = bot.removeTaskId != -1;
|
||||
|
||||
if (isReschedule) {
|
||||
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
|
||||
}
|
||||
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
|
||||
bot.removeTaskId = -1;
|
||||
botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false);
|
||||
}, time).getTaskId();
|
||||
|
||||
sender.sendMessage("This fakeplayer will be removed in " + h + "h " + m + "m " + s + "s" + (isReschedule ? " (rescheduled)" : ""));
|
||||
return true;
|
||||
}
|
||||
|
||||
botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false);
|
||||
sender.sendMessage(text("Removed fakeplayer: " + botName, NamedTextColor.GREEN));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleList(CommandSender sender, String[] args) {
|
||||
BotList botList = BotList.INSTANCE;
|
||||
|
||||
if (args.length < 2) {
|
||||
Map<World, List<String>> botMap = new HashMap<>();
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
botMap.put(world, new ArrayList<>());
|
||||
}
|
||||
|
||||
for (ServerBot bot : botList.bots) {
|
||||
Bot bukkitBot = bot.getBukkitEntity();
|
||||
botMap.get(bukkitBot.getWorld()).add(bukkitBot.getName());
|
||||
}
|
||||
|
||||
sender.sendMessage("Total number: (" + botList.bots.size() + "/" + FakeplayerConfig.limit + ")");
|
||||
for (World world : botMap.keySet()) {
|
||||
sender.sendMessage(world.getName() + "(" + botMap.get(world).size() + "): " + formatPlayerNameList(botMap.get(world)));
|
||||
}
|
||||
} else {
|
||||
World world = Bukkit.getWorld(args[1]);
|
||||
|
||||
if (world == null) {
|
||||
sender.sendMessage(text("Unknown world", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
List<String> snowBotList = new ArrayList<>();
|
||||
for (ServerBot bot : botList.bots) {
|
||||
Bot bukkitBot = bot.getBukkitEntity();
|
||||
if (bukkitBot.getWorld() == world) {
|
||||
snowBotList.add(bukkitBot.getName());
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(world.getName() + "(" + snowBotList.size() + "): " + formatPlayerNameList(snowBotList));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleAction(CommandSender sender, String[] args) {
|
||||
if (!FakeplayerConfig.canUseAction) {
|
||||
sender.sendMessage(text("Bot action feature is disabled!", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 3) {
|
||||
sender.sendMessage(text("Use /bot action <name> <action> to make fakeplayer do action", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
ServerBot bot = BotList.INSTANCE.getBotByName(args[1]);
|
||||
if (bot == null) {
|
||||
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args[2].toLowerCase()) {
|
||||
case "list" -> {
|
||||
sender.sendMessage(bot.getScoreboardName() + "'s action list:");
|
||||
for (int i = 0; i < bot.getBotActions().size(); i++) {
|
||||
sender.sendMessage(i + " " + bot.getBotActions().get(i).getName());
|
||||
}
|
||||
}
|
||||
case "start" -> executeActionStart(bot, sender, args);
|
||||
case "stop" -> executeActionStop(bot, sender, args);
|
||||
default -> sender.sendMessage(text("Unknown action command. Use: list, start, stop", NamedTextColor.RED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void executeActionStart(ServerBot bot, CommandSender sender, String[] args) {
|
||||
if (args.length < 4) {
|
||||
sender.sendMessage(text("Invalid action", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
ServerBotAction<?> action = Actions.getForName(args[3]);
|
||||
if (action == null) {
|
||||
sender.sendMessage(text("Invalid action", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
CraftPlayer player;
|
||||
if (sender instanceof CraftPlayer) {
|
||||
player = (CraftPlayer) sender;
|
||||
} else {
|
||||
player = bot.getBukkitEntity();
|
||||
}
|
||||
|
||||
String[] realArgs = Arrays.copyOfRange(args, 4, args.length);
|
||||
ServerBotAction<?> newAction;
|
||||
try {
|
||||
newAction = action.create();
|
||||
newAction.loadCommand(player.getHandle(), action.getArgument().parse(0, realArgs));
|
||||
} catch (IllegalArgumentException e) {
|
||||
sender.sendMessage(text("Action create error, please check your arguments, " + e.getMessage(), NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
if (bot.addBotAction(newAction, sender)) {
|
||||
sender.sendMessage("Action " + action.getName() + " has been issued to " + bot.getName().getString());
|
||||
}
|
||||
}
|
||||
|
||||
private void executeActionStop(ServerBot bot, CommandSender sender, String[] args) {
|
||||
if (args.length < 4) {
|
||||
sender.sendMessage(text("Invalid index", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
String index = args[3];
|
||||
if (index.equals("all")) {
|
||||
Set<ServerBotAction<?>> forRemoval = new HashSet<>();
|
||||
for (int i = 0; i < bot.getBotActions().size(); i++) {
|
||||
ServerBotAction<?> action = bot.getBotActions().get(i);
|
||||
BotActionStopEvent event = new BotActionStopEvent(
|
||||
bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender
|
||||
);
|
||||
event.callEvent();
|
||||
if (!event.isCancelled()) {
|
||||
forRemoval.add(action);
|
||||
action.stop(bot, BotActionStopEvent.Reason.COMMAND);
|
||||
}
|
||||
}
|
||||
bot.getBotActions().removeAll(forRemoval);
|
||||
sender.sendMessage(bot.getScoreboardName() + "'s action list cleared.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int i = Integer.parseInt(index);
|
||||
if (i < 0 || i >= bot.getBotActions().size()) {
|
||||
sender.sendMessage(text("Invalid index", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
ServerBotAction<?> action = bot.getBotActions().get(i);
|
||||
BotActionStopEvent event = new BotActionStopEvent(
|
||||
bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender
|
||||
);
|
||||
event.callEvent();
|
||||
if (!event.isCancelled()) {
|
||||
action.stop(bot, BotActionStopEvent.Reason.COMMAND);
|
||||
bot.getBotActions().remove(i);
|
||||
sender.sendMessage(bot.getScoreboardName() + "'s " + action.getName() + " stopped.");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(text("Invalid index", NamedTextColor.RED));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleConfig(CommandSender sender, String[] args) {
|
||||
if (!FakeplayerConfig.canModifyConfig) {
|
||||
sender.sendMessage(text("Bot config feature is disabled!", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 3) {
|
||||
sender.sendMessage(text("Use /bot config <name> <config> to modify fakeplayer's config", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
ServerBot bot = BotList.INSTANCE.getBotByName(args[1]);
|
||||
if (bot == null) {
|
||||
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Configs.getConfigNames().contains(args[2])) {
|
||||
sender.sendMessage(text("This config is not accept", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractBotConfig<?> config = bot.getConfig(Objects.requireNonNull(Configs.getConfig(args[2])));
|
||||
if (args.length < 4) {
|
||||
config.getMessage().forEach(sender::sendMessage);
|
||||
} else {
|
||||
String[] realArgs = Arrays.copyOfRange(args, 3, args.length);
|
||||
|
||||
BotConfigModifyEvent event = new BotConfigModifyEvent(bot.getBukkitEntity(), config.getName(), realArgs, sender);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
return true;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleSave(CommandSender sender, String[] args) {
|
||||
if (!FakeplayerConfig.canManualSaveAndLoad) {
|
||||
sender.sendMessage(text("Bot save/load feature is disabled!", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(text("Use /bot save <name> to save a fakeplayer", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
BotList botList = BotList.INSTANCE;
|
||||
ServerBot bot = botList.getBotByName(args[1]);
|
||||
|
||||
if (bot == null) {
|
||||
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true)) {
|
||||
sender.sendMessage(bot.getScoreboardName() + " saved to " + bot.createState.realName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleLoad(CommandSender sender, String[] args) {
|
||||
if (!FakeplayerConfig.canManualSaveAndLoad) {
|
||||
sender.sendMessage(text("Bot save/load feature is disabled!", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(text("Use /bot load <name> to load a fakeplayer", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
String realName = args[1];
|
||||
BotList botList = BotList.INSTANCE;
|
||||
if (!botList.getSavedBotList().contains(realName)) {
|
||||
sender.sendMessage(text("This fakeplayer is not saved", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (botList.loadNewBot(realName) == null) {
|
||||
sender.sendMessage(text("Can't load bot, please check", NamedTextColor.RED));
|
||||
} else {
|
||||
sender.sendMessage(text("Successfully loaded fakeplayer: " + realName, NamedTextColor.GREEN));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String formatPlayerNameList(@NotNull List<String> list) {
|
||||
if (list.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
String string = list.toString();
|
||||
return string.substring(1, string.length() - 1);
|
||||
}
|
||||
|
||||
private boolean canCreate(CommandSender sender, @NotNull String name) {
|
||||
BotList botList = BotList.INSTANCE;
|
||||
if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) {
|
||||
sender.sendMessage(text("This name is illegal", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Bukkit.getPlayerExact(name) != null || botList.getBotByName(name) != null) {
|
||||
sender.sendMessage(text("This player is in server", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FakeplayerConfig.unableNames.contains(name)) {
|
||||
sender.sendMessage(text("This name is not allowed", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (botList.bots.size() >= FakeplayerConfig.limit) {
|
||||
sender.sendMessage(text("Fakeplayer limit is full", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -147,4 +147,4 @@ public record BotCreateState(String realName, String name, String skinName, Stri
|
||||
return bot != null ? bot.getBukkitEntity() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,12 @@ public class BotList {
|
||||
}
|
||||
|
||||
public ServerBot loadNewBot(String realName) {
|
||||
return this.loadNewBot(realName, this.dataStorage);
|
||||
try {
|
||||
return this.loadNewBot(realName, this.dataStorage);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to load bot {}", realName, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ServerBot loadNewBot(String realName, IPlayerDataStorage playerIO) {
|
||||
@@ -198,7 +203,7 @@ public class BotList {
|
||||
this.server.server.getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled() && event.getReason() != BotRemoveEvent.RemoveReason.INTERNAL) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot.removeTaskId != -1) {
|
||||
@@ -240,18 +245,7 @@ public class BotList {
|
||||
}
|
||||
}
|
||||
|
||||
ServerLevel level = bot.level();
|
||||
int chunkX = bot.getBlockX() >> 4;
|
||||
int chunkZ = bot.getBlockZ() >> 4;
|
||||
if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(level, chunkX, chunkZ)) {
|
||||
level.removePlayerImmediately(bot, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
} else {
|
||||
io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(
|
||||
level, chunkX, chunkZ, () -> {
|
||||
level.removePlayerImmediately(bot, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
});
|
||||
}
|
||||
|
||||
bot.level().removePlayerImmediately(bot, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
this.bots.remove(bot);
|
||||
this.botsByName.remove(bot.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
|
||||
|
||||
@@ -68,6 +68,6 @@ public class BotRecipeBook extends ServerRecipeBook {
|
||||
|
||||
@Override
|
||||
public @NotNull Packed pack() {
|
||||
return new ServerRecipeBook.Packed(this.bookSettings.copy(), List.of(), List.of());
|
||||
return new Packed(this.bookSettings.copy(), List.of(), List.of());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +69,10 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.*;
|
||||
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
|
||||
@@ -84,9 +84,9 @@ import java.util.function.Predicate;
|
||||
|
||||
public class ServerBot extends ServerPlayer {
|
||||
|
||||
private final List<ServerBotAction<?>> actions;
|
||||
private final Map<Configs<?>, AbstractBotConfig<?>> configs;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final List<AbstractBotAction<?>> actions;
|
||||
private final Map<String, AbstractBotConfig<?, ?, ?>> configs;
|
||||
private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||
|
||||
public boolean resume = false;
|
||||
public BotCreateState createState;
|
||||
@@ -108,9 +108,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();
|
||||
|
||||
@@ -297,7 +297,7 @@ public class ServerBot extends ServerPlayer {
|
||||
return this;
|
||||
} else {
|
||||
this.isChangingDimension = true;
|
||||
fromLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
|
||||
fromLevel.removePlayerImmediately(this, RemovalReason.CHANGED_DIMENSION);
|
||||
this.unsetRemoved();
|
||||
this.setServerLevel(toLevel);
|
||||
this.teleportSetPosition(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives());
|
||||
@@ -389,14 +389,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()));
|
||||
}
|
||||
}
|
||||
@@ -429,9 +429,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);
|
||||
}
|
||||
@@ -441,9 +441,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,11 +641,11 @@ public class ServerBot extends ServerPlayer {
|
||||
private void runAction() {
|
||||
if (FakeplayerConfig.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 (!FakeplayerConfig.canUseAction) {
|
||||
return false;
|
||||
}
|
||||
@@ -659,7 +659,7 @@ public class ServerBot extends ServerPlayer {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<ServerBotAction<?>> getBotActions() {
|
||||
public List<AbstractBotAction<?>> getBotActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
@@ -670,11 +670,15 @@ 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 Collection<AbstractBotConfig<?, ?, ?>> getAllConfigs() {
|
||||
return configs.values();
|
||||
}
|
||||
|
||||
public <O, I, E extends AbstractBotConfig<O, I, E>> O getConfigValue(@NotNull AbstractBotConfig<O, I, E> config) {
|
||||
return this.getConfig(config).getValue();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -30,10 +30,10 @@ 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() {
|
||||
static {
|
||||
register(new ServerAttackAction(), AttackAction.class);
|
||||
register(new ServerBreakBlockAction(), BreakBlockAction.class);
|
||||
register(new ServerDropAction(), DropAction.class);
|
||||
@@ -55,7 +55,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<?> type) {
|
||||
if (!actionsByName.containsKey(action.getName())) {
|
||||
actionsByName.put(action.getName(), action);
|
||||
actionsByClass.put(type, action);
|
||||
@@ -64,14 +64,22 @@ public class Actions {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean register(@NotNull AbstractBotAction<?> action) {
|
||||
return register(action, action.getClass());
|
||||
}
|
||||
|
||||
public static boolean unregister(@NotNull String name) {
|
||||
// TODO add in custom action api
|
||||
return true;
|
||||
AbstractBotAction<?> action = actionsByName.remove(name);
|
||||
if (action != null) {
|
||||
actionsByClass.remove(action.getClass());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static Collection<ServerBotAction<?>> getAll() {
|
||||
public static Collection<AbstractBotAction<?>> getAll() {
|
||||
return actionsByName.values();
|
||||
}
|
||||
|
||||
@@ -81,12 +89,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,63 +20,40 @@ 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.*;
|
||||
|
||||
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 <Value, Type, E extends AbstractBotConfig<Value, Type, E>> @NotNull E register(AbstractBotConfig<Value, Type, E> instance) {
|
||||
configs.put(instance.getClass(), instance);
|
||||
return (E) instance;
|
||||
}
|
||||
}
|
||||
|
||||
+49
-29
@@ -17,34 +17,33 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.core.UUIDUtil;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.WrappedArgument;
|
||||
import org.leavesmc.leaves.event.bot.BotActionExecuteEvent;
|
||||
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
|
||||
import org.leavesmc.leaves.util.UpdateSuppressionException;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.*;
|
||||
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 CommandArgument argument;
|
||||
private final Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments;
|
||||
private final Supplier<E> creator;
|
||||
private UUID uuid;
|
||||
private int currentFork = 0;
|
||||
|
||||
private int initialTickDelay;
|
||||
private int initialTickInterval;
|
||||
@@ -57,13 +56,13 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
|
||||
private Consumer<E> onFail;
|
||||
private Consumer<E> onSuccess;
|
||||
private Consumer<E> onStop;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||
|
||||
public ServerBotAction(String name, CommandArgument argument, Supplier<E> creator) {
|
||||
public AbstractBotAction(String name, Supplier<E> creator) {
|
||||
this.name = name;
|
||||
this.argument = argument;
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.creator = creator;
|
||||
this.arguments = new HashMap<>();
|
||||
|
||||
this.cancel = false;
|
||||
this.setStartDelayTick(0);
|
||||
@@ -75,12 +74,40 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
|
||||
|
||||
public abstract Object asCraft();
|
||||
|
||||
public void provideActionData(@NotNull ActionData data) {
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.tickToNext = initialTickDelay;
|
||||
this.numberRemaining = this.getDoNumber();
|
||||
this.setCancelled(false);
|
||||
}
|
||||
|
||||
public void fork(int fork) {
|
||||
currentFork = fork;
|
||||
}
|
||||
|
||||
public <T> WrappedArgument<T> addArgument(String name, ArgumentType<T> type) {
|
||||
WrappedArgument<T> argument = new WrappedArgument<>(name, type);
|
||||
this.arguments
|
||||
.computeIfAbsent(currentFork, k -> new ArrayList<>())
|
||||
.add(Pair.of(name, argument));
|
||||
return argument;
|
||||
}
|
||||
|
||||
public Map<Integer, List<Pair<String, WrappedArgument<?>>>> getArguments() {
|
||||
return this.arguments;
|
||||
}
|
||||
|
||||
public void tryTick(ServerBot bot) {
|
||||
if (this.numberRemaining == 0) {
|
||||
this.stop(bot, BotActionStopEvent.Reason.DONE);
|
||||
@@ -168,19 +195,8 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
|
||||
}
|
||||
|
||||
public void setSuggestion(int n, BiFunction<CommandSender, String, Pair<List<String>, String>> suggestion) {
|
||||
this.argument.setSuggestion(n, suggestion);
|
||||
}
|
||||
|
||||
public void setSuggestion(int n, Pair<List<String>, String> suggestion) {
|
||||
this.setSuggestion(n, (sender, arg) -> suggestion);
|
||||
}
|
||||
|
||||
public void setSuggestion(int n, List<String> tabComplete) {
|
||||
this.setSuggestion(n, Pair.of(tabComplete, null));
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -188,10 +204,6 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
|
||||
return this.creator.get();
|
||||
}
|
||||
|
||||
public CommandArgument getArgument() {
|
||||
return this.argument;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
@@ -251,4 +263,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -17,14 +17,12 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class ServerStateBotAction<E extends ServerStateBotAction<E>> extends ServerBotAction<E> {
|
||||
public abstract class AbstractStateBotAction<E extends AbstractStateBotAction<E>> extends AbstractBotAction<E> {
|
||||
|
||||
public ServerStateBotAction(String name, CommandArgument argument, Supplier<E> creator) {
|
||||
super(name, argument, creator);
|
||||
public AbstractStateBotAction(String name, Supplier<E> creator) {
|
||||
super(name, creator);
|
||||
this.setDoNumber(-1);
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings;
|
||||
|
||||
public abstract class AbstractTimerBotAction<E extends AbstractTimerBotAction<E>> extends AbstractBotAction<E> {
|
||||
|
||||
public AbstractTimerBotAction(String name, Supplier<E> creator) {
|
||||
super(name, creator);
|
||||
this.addArgument("delay", integer(0))
|
||||
.suggests(strings("0", "5", "10", "20"))
|
||||
.setOptional(true);
|
||||
this.addArgument("interval", integer(0))
|
||||
.suggests(strings("20", "0", "5", "10"))
|
||||
.setOptional(true);
|
||||
this.addArgument("do_number", integer(-1))
|
||||
.suggests(((context, builder) -> builder.suggest("-1", Component.literal("do infinite times"))))
|
||||
.setOptional(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommand(@NotNull CommandContext context) {
|
||||
this.setStartDelayTick(context.getIntegerOrDefault("delay", 0));
|
||||
this.setDoIntervalTick(context.getIntegerOrDefault("interval", 20));
|
||||
this.setDoNumber(context.getIntegerOrDefault("do_number", 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void 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()));
|
||||
}
|
||||
}
|
||||
+24
-13
@@ -18,33 +18,37 @@
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class ServerUseBotAction<T extends ServerUseBotAction<T>> extends ServerTimerBotAction<T> {
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
|
||||
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) {
|
||||
super(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), supplier);
|
||||
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTickTimeout]"));
|
||||
public AbstractUseBotAction(String name, Supplier<T> supplier) {
|
||||
super(name, supplier);
|
||||
this.addArgument("use_timeout", integer(-1))
|
||||
.suggests((context, builder) -> {
|
||||
builder.suggest("-1", Component.literal("no use timeout"));
|
||||
builder.suggest("3", Component.literal("minimum bow shoot time"));
|
||||
builder.suggest("10", Component.literal("minimum trident shoot time"));
|
||||
})
|
||||
.setOptional(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
|
||||
super.loadCommand(player, result);
|
||||
this.useTickTimeout = result.readInt(-1);
|
||||
public void loadCommand(@NotNull CommandContext context) {
|
||||
super.loadCommand(context);
|
||||
this.useTickTimeout = context.getIntegerOrDefault("use_timeout", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,6 +114,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) {
|
||||
+1
-1
@@ -22,7 +22,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);
|
||||
|
||||
+1
-1
@@ -30,7 +30,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);
|
||||
|
||||
+1
-1
@@ -21,7 +21,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);
|
||||
|
||||
+1
-1
@@ -26,7 +26,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);
|
||||
|
||||
+1
-1
@@ -21,7 +21,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);
|
||||
|
||||
+51
-36
@@ -17,40 +17,61 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.commands.arguments.coordinates.Coordinates;
|
||||
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
|
||||
import net.minecraft.commands.arguments.selector.EntitySelector;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.entity.Player;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftLookAction;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ServerLookAction extends ServerBotAction<ServerLookAction> {
|
||||
public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
|
||||
|
||||
private static final Vector ZERO_VECTOR = new Vector(0, 0, 0);
|
||||
private static final DecimalFormat DF = new DecimalFormat("0.0");
|
||||
|
||||
private Vector pos = ZERO_VECTOR;
|
||||
private ServerPlayer target = null;
|
||||
|
||||
public ServerLookAction() {
|
||||
super("look", CommandArgument.of(CommandArgumentType.STRING, CommandArgumentType.DOUBLE, CommandArgumentType.DOUBLE), ServerLookAction::new);
|
||||
this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ?
|
||||
Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of(DF.format(player.getX()))).toList(), "<Player>|<X>") :
|
||||
Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of("0")).toList(), "<Player>|<X>")
|
||||
);
|
||||
this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getY())), "<Y>") : Pair.of(List.of("0"), "<Y>"));
|
||||
this.setSuggestion(2, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getZ())), "<Z>") : Pair.of(List.of("0"), "<Z>"));
|
||||
super("look", ServerLookAction::new);
|
||||
declarePlayerBranch();
|
||||
declareLocationBranch();
|
||||
}
|
||||
|
||||
private void declarePlayerBranch() {
|
||||
this.fork(0);
|
||||
this.addArgument("player", EntityArgument.player())
|
||||
.setOptional(true);
|
||||
}
|
||||
|
||||
private void declareLocationBranch() {
|
||||
this.fork(1);
|
||||
this.addArgument("location", Vec3Argument.vec3(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
EntitySelector selector = context.getArgumentOrDefault("player", EntitySelector.class, null);
|
||||
Coordinates location = context.getArgumentOrDefault("location", Coordinates.class, null);
|
||||
CommandSourceStack source = context.getSource();
|
||||
if (selector == null && location == null) {
|
||||
Entity sender = source.getEntityOrException();
|
||||
this.setPos(new Vector(sender.getX(), sender.getY(), sender.getZ()));
|
||||
} else if (selector != null) {
|
||||
ServerPlayer player = selector.findSinglePlayer(source);
|
||||
this.setTarget(player);
|
||||
} else {
|
||||
Vec3 vector = location.getPosition(source);
|
||||
this.setPos(new Vector(vector.x, vector.y, vector.z));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,6 +115,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) {
|
||||
@@ -104,22 +135,6 @@ public class ServerLookAction extends ServerBotAction<ServerLookAction> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
|
||||
String nameOrX = result.readString(player.getScoreboardName());
|
||||
ServerPlayer player1 = player.getServer().getPlayerList().getPlayerByName(nameOrX);
|
||||
if (player1 != null) {
|
||||
this.setTarget(player1);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Vector vector = result.readVectorYZ(Double.parseDouble(nameOrX));
|
||||
this.setPos(vector);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Invalid vector");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asCraft() {
|
||||
return new CraftLookAction(this);
|
||||
|
||||
+4
-5
@@ -23,16 +23,15 @@ import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftMountAction;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ServerMountAction extends ServerBotAction<ServerMountAction> {
|
||||
public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
|
||||
|
||||
public ServerMountAction() {
|
||||
super("mount", CommandArgument.EMPTY, ServerMountAction::new);
|
||||
super("mount", ServerMountAction::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,8 +39,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();
|
||||
|
||||
+29
-16
@@ -17,39 +17,46 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction;
|
||||
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ServerMoveAction extends ServerStateBotAction<ServerMoveAction> {
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings;
|
||||
|
||||
private static final Pair<List<String>, String> suggestions = Pair.of(
|
||||
Arrays.stream(MoveDirection.values()).map((it) -> it.name).toList(),
|
||||
"<Direction>"
|
||||
);
|
||||
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
|
||||
));
|
||||
private MoveDirection direction = MoveDirection.FORWARD;
|
||||
|
||||
public ServerMoveAction() {
|
||||
super("move", CommandArgument.of(CommandArgumentType.ofEnum(MoveDirection.class)), ServerMoveAction::new);
|
||||
this.setSuggestion(0, suggestions);
|
||||
super("move", ServerMoveAction::new);
|
||||
this.addArgument("direction", StringArgumentType.word())
|
||||
.suggests(strings(
|
||||
Arrays.stream(MoveDirection.values())
|
||||
.map((it) -> it.name)
|
||||
.toList()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
|
||||
this.direction = result.read(MoveDirection.class);
|
||||
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
String raw = context.getArgument("direction", String.class);
|
||||
MoveDirection direction = NAME_TO_DIRECTION.get(raw);
|
||||
if (direction == null) {
|
||||
throw new IllegalArgumentException("Invalid direction");
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
|
||||
}
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,6 +81,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;
|
||||
}
|
||||
|
||||
+28
-19
@@ -17,42 +17,44 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.entity.Player;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ServerRotationAction extends ServerBotAction<ServerRotationAction> {
|
||||
public class ServerRotationAction extends AbstractBotAction<ServerRotationAction> {
|
||||
|
||||
private static final DecimalFormat DF = new DecimalFormat("0.00");
|
||||
|
||||
public ServerRotationAction() {
|
||||
super("rotation", CommandArgument.of(CommandArgumentType.FLOAT, CommandArgumentType.FLOAT), ServerRotationAction::new);
|
||||
this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getYaw())), "[yaw]") : Pair.of(List.of("0"), "<yaw>"));
|
||||
this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getPitch())), "[pitch]") : Pair.of(List.of("0"), "<pitch>"));
|
||||
super("rotation", ServerRotationAction::new);
|
||||
this.addArgument("yaw", FloatArgumentType.floatArg(-180, 180))
|
||||
.suggests((context, builder) -> builder.suggest(
|
||||
DF.format(context.getSource().getEntityOrException().getYRot()),
|
||||
Component.literal("current player yaw")
|
||||
))
|
||||
.setOptional(true);
|
||||
this.addArgument("pitch", FloatArgumentType.floatArg(-90, 90))
|
||||
.suggests((context, builder) -> builder.suggest(
|
||||
DF.format(context.getSource().getEntityOrException().getXRot()),
|
||||
Component.literal("current player pitch")
|
||||
))
|
||||
.setOptional(true);
|
||||
}
|
||||
|
||||
private float yaw = 0.0f;
|
||||
private float pitch = 0.0f;
|
||||
|
||||
@Override
|
||||
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
|
||||
try {
|
||||
this.yaw = result.readFloat(Objects.requireNonNull(player).getYRot());
|
||||
this.pitch = result.readFloat(player.getXRot());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("No valid rotation specified", e);
|
||||
}
|
||||
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
this.yaw = context.getFloatOrDefault("yaw", context.getSource().getEntityOrException().getYRot());
|
||||
this.pitch = context.getFloatOrDefault("pitch", context.getSource().getEntityOrException().getXRot());
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
@@ -71,6 +73,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) {
|
||||
|
||||
+2
-3
@@ -19,14 +19,13 @@ package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction;
|
||||
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
|
||||
|
||||
public class ServerSneakAction extends ServerStateBotAction<ServerSneakAction> {
|
||||
public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction> {
|
||||
|
||||
public ServerSneakAction() {
|
||||
super("sneak", CommandArgument.EMPTY, ServerSneakAction::new);
|
||||
super("sneak", ServerSneakAction::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-3
@@ -21,13 +21,12 @@ import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction;
|
||||
|
||||
public class ServerSwapAction extends ServerBotAction<ServerSwapAction> {
|
||||
public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
|
||||
|
||||
public ServerSwapAction() {
|
||||
super("swap", CommandArgument.EMPTY, ServerSwapAction::new);
|
||||
super("swap", ServerSwapAction::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-3
@@ -20,13 +20,12 @@ package org.leavesmc.leaves.bot.agent.actions;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction;
|
||||
|
||||
public class ServerSwimAction extends ServerStateBotAction<ServerSwimAction> {
|
||||
public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
|
||||
|
||||
public ServerSwimAction() {
|
||||
super("swim", CommandArgument.EMPTY, ServerSwimAction::new);
|
||||
super("swim", ServerSwimAction::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.actions;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentResult;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class ServerTimerBotAction<E extends ServerTimerBotAction<E>> extends ServerBotAction<E> {
|
||||
|
||||
public ServerTimerBotAction(String name, Supplier<E> creator) {
|
||||
this(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), creator);
|
||||
}
|
||||
|
||||
public ServerTimerBotAction(String name, CommandArgument argument, Supplier<E> creator) {
|
||||
super(name, argument, creator);
|
||||
this.setSuggestion(0, Pair.of(List.of("0"), "[TickDelay]"));
|
||||
this.setSuggestion(1, Pair.of(List.of("20"), "[TickInterval]"));
|
||||
this.setSuggestion(2, Pair.of(List.of("1", "-1"), "[DoNumber]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
|
||||
this.setStartDelayTick(result.readInt(0));
|
||||
this.setDoIntervalTick(result.readInt(20));
|
||||
this.setDoNumber(result.readInt(1));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,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);
|
||||
|
||||
+1
-1
@@ -34,7 +34,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);
|
||||
|
||||
+1
-1
@@ -24,7 +24,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);
|
||||
|
||||
+1
-1
@@ -25,7 +25,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);
|
||||
|
||||
+1
-1
@@ -25,7 +25,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);
|
||||
|
||||
+1
-1
@@ -26,7 +26,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);
|
||||
|
||||
+1
-1
@@ -25,7 +25,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);
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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.command.CommandContext;
|
||||
import org.leavesmc.leaves.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<Value, Type, E extends AbstractBotConfig<Value, Type, E>> {
|
||||
private final String name;
|
||||
private final WrappedArgument<Type> argument;
|
||||
private final Supplier<E> creator;
|
||||
|
||||
protected ServerBot bot;
|
||||
|
||||
public AbstractBotConfig(String name, ArgumentType<Type> 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<Value, Type, E> setBot(ServerBot bot) {
|
||||
this.bot = bot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public E create() {
|
||||
return creator.get();
|
||||
}
|
||||
|
||||
public abstract Value getValue();
|
||||
|
||||
public abstract void setValue(Value value) throws CommandSyntaxException;
|
||||
|
||||
public abstract Value 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<Type> 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;
|
||||
}
|
||||
}
|
||||
+11
-12
@@ -17,23 +17,17 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.configs;
|
||||
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.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 = FakeplayerConfig.canSendDataAlways;
|
||||
}
|
||||
|
||||
@@ -47,16 +41,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, FakeplayerConfig.canSendDataAlways));
|
||||
this.setValue(nbt.getBooleanOr(getName(), FakeplayerConfig.canSendDataAlways));
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -17,25 +17,19 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.configs;
|
||||
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import fun.bm.lophine.config.modules.experiment.CommandConfig;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.waypoints.ServerWaypointManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.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 = FakeplayerConfig.enableLocatorBar && CommandConfig.waypoint;
|
||||
}
|
||||
|
||||
@@ -45,7 +39,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) {
|
||||
@@ -55,15 +49,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, FakeplayerConfig.enableLocatorBar));
|
||||
this.setValue(nbt.getBooleanOr(getName(), FakeplayerConfig.enableLocatorBar && CommandConfig.waypoint));
|
||||
}
|
||||
}
|
||||
+22
-14
@@ -17,22 +17,28 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.configs;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.agent.AbstractBotConfig;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.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
|
||||
@@ -42,22 +48,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, FakeplayerConfig.getSimulationDistance(this.bot)));
|
||||
this.setValue(nbt.getIntOr(getName(), FakeplayerConfig.getSimulationDistance(this.bot)));
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -17,21 +17,16 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.configs;
|
||||
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.agent.AbstractBotConfig;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.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
|
||||
@@ -44,15 +39,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, FakeplayerConfig.canSkipSleep));
|
||||
this.setValue(nbt.getBooleanOr(getName(), FakeplayerConfig.canSkipSleep));
|
||||
}
|
||||
}
|
||||
|
||||
+14
-15
@@ -17,23 +17,20 @@
|
||||
|
||||
package org.leavesmc.leaves.bot.agent.configs;
|
||||
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.agent.AbstractBotConfig;
|
||||
import org.leavesmc.leaves.command.CommandArgument;
|
||||
import org.leavesmc.leaves.command.CommandArgumentType;
|
||||
import org.leavesmc.leaves.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 = FakeplayerConfig.canSpawnPhantom;
|
||||
}
|
||||
|
||||
@@ -48,22 +45,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, FakeplayerConfig.canSpawnPhantom));
|
||||
this.setValue(nbt.getBooleanOr(getName(), FakeplayerConfig.canSpawnPhantom));
|
||||
}
|
||||
}
|
||||
|
||||
+29
-13
@@ -17,28 +17,39 @@
|
||||
|
||||
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 fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.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 = FakeplayerConfig.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;
|
||||
@@ -53,12 +64,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, FakeplayerConfig.tickType.name())));
|
||||
String raw = nbt.getStringOr(getName(), FakeplayerConfig.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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
package org.leavesmc.leaves.command;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class CommandArgument {
|
||||
|
||||
public static final CommandArgument EMPTY = new CommandArgument();
|
||||
|
||||
private static final Pair<List<String>, String> EMPTY_SUGGESTION_RESULT = Pair.of(List.of(), null);
|
||||
private static final BiFunction<CommandSender, String, Pair<List<String>, String>> EMPTY_SUGGESTION = (sender, arg) -> EMPTY_SUGGESTION_RESULT;
|
||||
|
||||
private final List<BiFunction<CommandSender, String, Pair<List<String>, String>>> suggestions;
|
||||
private final List<CommandArgumentType<?>> argumentTypes;
|
||||
|
||||
private CommandArgument(CommandArgumentType<?>... argumentTypes) {
|
||||
this.argumentTypes = List.of(argumentTypes);
|
||||
this.suggestions = new ArrayList<>();
|
||||
for (int i = 0; i < argumentTypes.length; i++) {
|
||||
suggestions.add(EMPTY_SUGGESTION);
|
||||
}
|
||||
}
|
||||
|
||||
public static CommandArgument of(CommandArgumentType<?>... argumentTypes) {
|
||||
return new CommandArgument(argumentTypes);
|
||||
}
|
||||
|
||||
public List<CommandArgumentType<?>> getArgumentTypes() {
|
||||
return argumentTypes;
|
||||
}
|
||||
|
||||
public CommandArgument setSuggestion(int n, BiFunction<CommandSender, String, Pair<List<String>, String>> suggestion) {
|
||||
this.suggestions.set(n, suggestion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandArgument setSuggestion(int n, Pair<List<String>, String> suggestion) {
|
||||
return this.setSuggestion(n, (sender, arg) -> suggestion);
|
||||
}
|
||||
|
||||
public CommandArgument setSuggestion(int n, List<String> tabComplete) {
|
||||
return this.setSuggestion(n, Pair.of(tabComplete, null));
|
||||
}
|
||||
|
||||
public Pair<List<String>, String> suggestion(int n, CommandSender sender, String arg) {
|
||||
if (suggestions.size() > n) {
|
||||
return suggestions.get(n).apply(sender, arg);
|
||||
} else {
|
||||
return EMPTY_SUGGESTION.apply(sender, arg);
|
||||
}
|
||||
}
|
||||
|
||||
public CommandArgumentResult parse(int index, String @NotNull [] args) {
|
||||
Object[] result = new Object[argumentTypes.size()];
|
||||
Arrays.fill(result, null);
|
||||
for (int i = index, j = 0; i < args.length && j < result.length; i++, j++) {
|
||||
result[j] = argumentTypes.get(j).parse(args[i]);
|
||||
}
|
||||
return new CommandArgumentResult(new ArrayList<>(Arrays.asList(result)));
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package org.leavesmc.leaves.command;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CommandArgumentResult {
|
||||
|
||||
private final List<Object> result;
|
||||
|
||||
public CommandArgumentResult(List<Object> result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public int readInt(int def) {
|
||||
return Objects.requireNonNullElse(read(Integer.class), def);
|
||||
}
|
||||
|
||||
public double readDouble(double def) {
|
||||
return Objects.requireNonNullElse(read(Double.class), def);
|
||||
}
|
||||
|
||||
public float readFloat(float def) {
|
||||
return Objects.requireNonNullElse(read(Float.class), def);
|
||||
}
|
||||
|
||||
public String readString(String def) {
|
||||
return Objects.requireNonNullElse(read(String.class), def);
|
||||
}
|
||||
|
||||
public boolean readBoolean(boolean def) {
|
||||
return Objects.requireNonNullElse(read(Boolean.class), def);
|
||||
}
|
||||
|
||||
public BlockPos readPos() {
|
||||
Integer[] pos = {read(Integer.class), read(Integer.class), read(Integer.class)};
|
||||
for (Integer po : pos) {
|
||||
if (po == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new BlockPos(pos[0], pos[1], pos[2]);
|
||||
}
|
||||
|
||||
public @Nullable Vector readVector() {
|
||||
Double[] pos = {read(Double.class), read(Double.class), read(Double.class)};
|
||||
for (Double po : pos) {
|
||||
if (po == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new Vector(pos[0], pos[1], pos[2]);
|
||||
}
|
||||
|
||||
public @NotNull Vector readVectorYZ(double x) {
|
||||
Double[] pos = {x, read(Double.class), read(Double.class)};
|
||||
for (Double po : pos) {
|
||||
if (po == null) {
|
||||
throw new IllegalArgumentException("Failed to read vector!");
|
||||
}
|
||||
}
|
||||
return new Vector(pos[0], pos[1], pos[2]);
|
||||
}
|
||||
|
||||
public Object readObject() {
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return result.removeFirst();
|
||||
}
|
||||
|
||||
public <T> T read(Class<T> tClass, T def) {
|
||||
return Objects.requireNonNullElse(read(tClass), def);
|
||||
}
|
||||
|
||||
public <T> T read(Class<T> tClass) {
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object obj = result.removeFirst();
|
||||
if (tClass.isInstance(obj)) {
|
||||
return tClass.cast(obj);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.leavesmc.leaves.command;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public abstract class CommandArgumentType<E> {
|
||||
|
||||
public static final CommandArgumentType<String> STRING = CommandArgumentType.string();
|
||||
public static final CommandArgumentType<Integer> INTEGER = CommandArgumentType.of(Integer.class, Integer::parseInt);
|
||||
public static final CommandArgumentType<Double> DOUBLE = CommandArgumentType.of(Double.class, Double::parseDouble);
|
||||
public static final CommandArgumentType<Float> FLOAT = CommandArgumentType.of(Float.class, Float::parseFloat);
|
||||
public static final CommandArgumentType<Boolean> BOOLEAN = CommandArgumentType.of(Boolean.class, Boolean::parseBoolean);
|
||||
|
||||
private final Class<E> type;
|
||||
|
||||
private CommandArgumentType(Class<E> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(value = "_, _ -> new", pure = true)
|
||||
public static <E> CommandArgumentType<E> of(Class<E> type, Function<String, E> parse) {
|
||||
return new CommandArgumentType<>(type) {
|
||||
@Override
|
||||
public E parse(@NotNull String arg) {
|
||||
try {
|
||||
return parse.apply(arg);
|
||||
} catch (Exception ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public static <E extends Enum<E>> CommandArgumentType<E> ofEnum(Class<E> type) {
|
||||
return of(type, (string -> Enum.valueOf(type, string.toUpperCase())));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(value = " -> new", pure = true)
|
||||
private static CommandArgumentType<String> string() {
|
||||
return new CommandArgumentType<>(String.class) {
|
||||
@Override
|
||||
public String parse(@NotNull String arg) {
|
||||
return arg;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Class<E> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public abstract E parse(@NotNull String arg);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.leavesmc.leaves.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.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.CustomArgumentType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BotArgument implements CustomArgumentType<ServerBot, String> {
|
||||
@Override
|
||||
public ArgumentType<String> getBaseArgumentType() {
|
||||
return StringArgumentType.word();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerBot transform(String value) throws CommandSyntaxException {
|
||||
ServerBot bot = BotList.INSTANCE.getBotByName(value);
|
||||
if (bot == null) {
|
||||
throw new CommandSyntaxException(
|
||||
CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(),
|
||||
Component.literal("Bot with name '" + value + "' does not exist")
|
||||
);
|
||||
}
|
||||
return bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Suggestions> getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException {
|
||||
Collection<ServerBot> bots = BotList.INSTANCE.bots;
|
||||
if (bots.isEmpty()) {
|
||||
return builder
|
||||
.suggest("<NO BOT EXISTS>", Component.literal("There are no bots in the server, create one first."))
|
||||
.buildFuture();
|
||||
}
|
||||
bots.stream().map(ServerBot::getScoreboardName).forEach(builder::suggest);
|
||||
return builder.buildFuture();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.command.RootNode;
|
||||
import org.leavesmc.leaves.command.bot.subcommands.*;
|
||||
|
||||
import static org.leavesmc.leaves.command.CommandUtils.registerPermissions;
|
||||
|
||||
public class BotCommand extends RootNode {
|
||||
private static final String PERM_BASE = "bukkit.command.bot";
|
||||
|
||||
public BotCommand() {
|
||||
super("bot", PERM_BASE);
|
||||
this.children(
|
||||
ListCommand::new,
|
||||
ConfigCommand::new,
|
||||
RemoveCommand::new,
|
||||
LoadCommand::new,
|
||||
SaveCommand::new,
|
||||
ActionCommand::new,
|
||||
CreateCommand::new
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
|
||||
registerPermissions(PERM_BASE, this.children);
|
||||
return super.compile();
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSender sender) {
|
||||
return sender.hasPermission(PERM_BASE);
|
||||
}
|
||||
|
||||
public static boolean hasPermission(@NotNull CommandSender sender, String... subcommand) {
|
||||
return hasPermission(PERM_BASE, sender, subcommand);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.command.LiteralNode;
|
||||
|
||||
public abstract class BotSubcommand extends LiteralNode {
|
||||
|
||||
protected BotSubcommand(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return BotCommand.hasPermission(source.getSender(), this.name);
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.CustomArgumentNode;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
import org.leavesmc.leaves.command.bot.subcommands.action.ListCommand;
|
||||
import org.leavesmc.leaves.command.bot.subcommands.action.StartCommand;
|
||||
import org.leavesmc.leaves.command.bot.subcommands.action.StopCommand;
|
||||
|
||||
public class ActionCommand extends BotSubcommand {
|
||||
|
||||
public ActionCommand() {
|
||||
super("action");
|
||||
children(BotArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return FakeplayerConfig.canUseAction && super.requires(source);
|
||||
}
|
||||
|
||||
public static class BotArgument extends CustomArgumentNode<ServerBot, String> {
|
||||
|
||||
private BotArgument() {
|
||||
super("bot", new org.leavesmc.leaves.command.bot.BotArgument());
|
||||
children(
|
||||
StartCommand::new,
|
||||
StopCommand::new,
|
||||
ListCommand::new
|
||||
);
|
||||
}
|
||||
|
||||
public static @NotNull ServerBot getBot(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
return context.getCustomArgument(BotArgument.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.bot.agent.Configs;
|
||||
import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.CustomArgumentNode;
|
||||
import org.leavesmc.leaves.command.LiteralNode;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return FakeplayerConfig.canModifyConfig && super.requires(source);
|
||||
}
|
||||
|
||||
private static class BotArgument extends CustomArgumentNode<ServerBot, String> {
|
||||
|
||||
private BotArgument() {
|
||||
super("bot", new org.leavesmc.leaves.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);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = BotArgument.getBot(context);
|
||||
CommandSender sender = context.getSender();
|
||||
Collection<AbstractBotConfig<?, ?, ?>> botConfigs = bot.getAllConfigs();
|
||||
sender.sendMessage(join(spaces(),
|
||||
text("Bot", GRAY),
|
||||
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
|
||||
text("configs:", GRAY)
|
||||
));
|
||||
for (AbstractBotConfig<?, ?, ?> botConfig : botConfigs) {
|
||||
sender.sendMessage(join(spaces(),
|
||||
botConfig.getNameComponent(),
|
||||
text("=", GRAY),
|
||||
text(String.valueOf(botConfig.getValue()), AQUA)
|
||||
));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConfigNode<Value> extends LiteralNode {
|
||||
private final AbstractBotConfig<Value, ?, ?> config;
|
||||
|
||||
private ConfigNode(@NotNull AbstractBotConfig<Value, ?, ?> 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<Value, ?, ?> 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<Value, ?, ?> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
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.bot.BotCreateState;
|
||||
import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.command.ArgumentNode;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
import org.leavesmc.leaves.event.bot.BotCreateEvent;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.minecraft.commands.arguments.DimensionArgument.getDimension;
|
||||
|
||||
public class CreateCommand extends BotSubcommand {
|
||||
|
||||
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, bot name must be 4-16 characters and contain only letters, numbers, and underscores.", 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 (FakeplayerConfig.unableNames.contains(name)) {
|
||||
sender.sendMessage(text("This name is not allowed in this server", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (botList.bots.size() >= FakeplayerConfig.limit) {
|
||||
sender.sendMessage(text("Bot number limit exceeded", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class NameArgument extends ArgumentNode<String> {
|
||||
|
||||
private 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> {
|
||||
|
||||
private 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> {
|
||||
|
||||
private WorldArgument() {
|
||||
super("world", DimensionArgument.dimension());
|
||||
children(LocationArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return source.getSender() instanceof ConsoleCommandSender;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LocationArgument extends ArgumentNode<Coordinates> {
|
||||
|
||||
private LocationArgument() {
|
||||
super("location", Vec3Argument.vec3(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(CommandContext context) throws CommandSyntaxException {
|
||||
return handleCreateCommand(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
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.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.ArgumentNode;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
|
||||
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 BotSubcommand {
|
||||
|
||||
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(FakeplayerConfig.limit, AQUA).hoverEvent(showText(text("bot count limit")))
|
||||
));
|
||||
context.getSender().sendMessage(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static @Nullable Component getBotListMessage(@NotNull World world) {
|
||||
List<ServerBot> botsInLevel = BotList.INSTANCE.bots.stream()
|
||||
.filter((bot) -> bot.getBukkitEntity().getWorld().equals(world))
|
||||
.toList();
|
||||
if (botsInLevel.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Component botsMsg = botsInLevel.stream()
|
||||
.map(Player::getDisplayName)
|
||||
.map(PaperAdventure::asAdventure)
|
||||
.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> {
|
||||
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.ArgumentNode;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static io.papermc.paper.adventure.PaperAdventure.asAdventure;
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
|
||||
public class LoadCommand extends BotSubcommand {
|
||||
|
||||
public LoadCommand() {
|
||||
super("load");
|
||||
children(BotNameArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return FakeplayerConfig.canManualSaveAndLoad && super.requires(source);
|
||||
}
|
||||
|
||||
private static class BotNameArgument extends ArgumentNode<String> {
|
||||
|
||||
private BotNameArgument() {
|
||||
super("bot_name", StringArgumentType.word());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
String botName = context.getArgument(BotNameArgument.class);
|
||||
BotList botList = BotList.INSTANCE;
|
||||
CommandSender sender = context.getSender();
|
||||
if (!botList.getSavedBotList().contains(botName)) {
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
|
||||
}
|
||||
|
||||
ServerBot bot = botList.loadNewBot(botName);
|
||||
if (bot == null) {
|
||||
sender.sendMessage(text("Failed to load bot, please check log", NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
sender.sendMessage(join(
|
||||
spaces(),
|
||||
text("Successfully loaded bot", NamedTextColor.GRAY),
|
||||
asAdventure(bot.getDisplayName())
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<Suggestions> getSuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) {
|
||||
BotList botList = BotList.INSTANCE;
|
||||
Set<String> bots = botList.getSavedBotList().keySet();
|
||||
if (bots.isEmpty()) {
|
||||
return builder
|
||||
.suggest("<NO SAVED BOT EXISTS>", net.minecraft.network.chat.Component.literal("There are no bots saved before, save one first."))
|
||||
.buildFuture();
|
||||
}
|
||||
bots.forEach(builder::suggest);
|
||||
return builder.buildFuture();
|
||||
}
|
||||
}
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import io.papermc.paper.adventure.PaperAdventure;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.ArgumentNode;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.CustomArgumentNode;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
import org.leavesmc.leaves.event.bot.BotRemoveEvent;
|
||||
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||
import static net.minecraft.network.chat.Component.literal;
|
||||
|
||||
public class RemoveCommand extends BotSubcommand {
|
||||
|
||||
public RemoveCommand() {
|
||||
super("remove");
|
||||
children(BotArgument::new);
|
||||
}
|
||||
|
||||
private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender sender) {
|
||||
boolean success = BotList.INSTANCE.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false);
|
||||
if (!success) {
|
||||
sender = sender == null ? Bukkit.getConsoleSender() : sender;
|
||||
sender.sendMessage(text("Bot remove canceled by a plugin", RED));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static class BotArgument extends CustomArgumentNode<ServerBot, String> {
|
||||
|
||||
private BotArgument() {
|
||||
super("bot", new org.leavesmc.leaves.command.bot.BotArgument());
|
||||
children(RemoveTimeArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = context.getCustomArgument(BotArgument.class);
|
||||
return removeBot(bot, context.getSender());
|
||||
}
|
||||
}
|
||||
|
||||
private static class RemoveTimeArgument extends ArgumentNode<String> {
|
||||
|
||||
private RemoveTimeArgument() {
|
||||
super("remove_time", StringArgumentType.word());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
String removeTimeStr = context.getArgument("remove_time", String.class);
|
||||
int removeTimeSeconds = parseRemoveTime(removeTimeStr);
|
||||
ServerBot bot = context.getCustomArgument(BotArgument.class);
|
||||
CommandSender sender = context.getSender();
|
||||
|
||||
boolean isReschedule = bot.removeTaskId != -1;
|
||||
|
||||
if (isReschedule) {
|
||||
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
|
||||
}
|
||||
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
|
||||
bot.removeTaskId = -1;
|
||||
removeBot(bot, sender);
|
||||
}, removeTimeSeconds * 20L).getTaskId();
|
||||
|
||||
sender.sendMessage(join(spaces(),
|
||||
text("Bot", GRAY),
|
||||
PaperAdventure.asAdventure(bot.getDisplayName()),
|
||||
text("scheduled for removal in", GRAY),
|
||||
text(formatSeconds(removeTimeSeconds), AQUA),
|
||||
text(isReschedule ? "(rescheduled)" : "", GRAY)
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int parseRemoveTime(String timeStr) throws CommandSyntaxException {
|
||||
if (timeStr == null || timeStr.trim().isEmpty()) {
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
|
||||
}
|
||||
|
||||
if (!timeStr.matches("^[\\d\\shmsHMS]+$")) {
|
||||
throw new CommandSyntaxException(
|
||||
CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(),
|
||||
literal("Invalid time format: " + timeStr)
|
||||
);
|
||||
}
|
||||
|
||||
String remaining = timeStr.replaceAll("\\d+[hmsHMS]", "").trim();
|
||||
if (!remaining.isEmpty() && remaining.matches(".*\\d+.*")) {
|
||||
throw new CommandSyntaxException(
|
||||
CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(),
|
||||
literal("Found trailing numbers without unit: " + timeStr)
|
||||
);
|
||||
}
|
||||
|
||||
Matcher matcher = Pattern.compile("(\\d+)([hmsHMS])").matcher(timeStr);
|
||||
int seconds = 0;
|
||||
boolean foundMatch = false;
|
||||
|
||||
while (matcher.find()) {
|
||||
foundMatch = true;
|
||||
int value = Integer.parseInt(matcher.group(1));
|
||||
switch (matcher.group(2).toLowerCase()) {
|
||||
case "h":
|
||||
seconds += value * 3600;
|
||||
break;
|
||||
case "m":
|
||||
seconds += value * 60;
|
||||
break;
|
||||
case "s":
|
||||
seconds += value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatch) {
|
||||
throw new CommandSyntaxException(
|
||||
CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(),
|
||||
literal("No valid time units found in: " + timeStr)
|
||||
);
|
||||
}
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
private static @NotNull String formatSeconds(int totalSeconds) {
|
||||
int h = totalSeconds / 3600;
|
||||
int m = (totalSeconds % 3600) / 60;
|
||||
int s = totalSeconds % 60;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (h > 0) {
|
||||
sb.append(h).append("h");
|
||||
}
|
||||
if (m > 0) {
|
||||
sb.append(m).append("m");
|
||||
}
|
||||
if (s > 0) {
|
||||
sb.append(s).append("s");
|
||||
}
|
||||
if (sb.isEmpty()) {
|
||||
sb.append("0s");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.BotList;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.CustomArgumentNode;
|
||||
import org.leavesmc.leaves.command.bot.BotSubcommand;
|
||||
import org.leavesmc.leaves.event.bot.BotRemoveEvent;
|
||||
|
||||
import static io.papermc.paper.adventure.PaperAdventure.asAdventure;
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
|
||||
public class SaveCommand extends BotSubcommand {
|
||||
|
||||
public SaveCommand() {
|
||||
super("save");
|
||||
children(BotArgument::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requires(@NotNull CommandSourceStack source) {
|
||||
return FakeplayerConfig.canManualSaveAndLoad && super.requires(source);
|
||||
}
|
||||
|
||||
private static class BotArgument extends CustomArgumentNode<ServerBot, String> {
|
||||
|
||||
private BotArgument() {
|
||||
super("bot", new org.leavesmc.leaves.command.bot.BotArgument());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = context.getCustomArgument(BotArgument.class);
|
||||
CommandSender sender = context.getSender();
|
||||
BotList botList = BotList.INSTANCE;
|
||||
|
||||
boolean success = botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true);
|
||||
if (success) {
|
||||
sender.sendMessage(join(spaces(),
|
||||
text("Successfully saved bot", NamedTextColor.GRAY),
|
||||
asAdventure(bot.getDisplayName()),
|
||||
text("as " + bot.createState.realName(), NamedTextColor.GRAY)
|
||||
));
|
||||
} else {
|
||||
sender.sendMessage(text("Bot save canceled by a plugin", NamedTextColor.RED));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands.action;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.LiteralNode;
|
||||
import org.leavesmc.leaves.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;
|
||||
import static net.kyori.adventure.text.event.HoverEvent.showText;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.AQUA;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
|
||||
|
||||
public class ListCommand extends LiteralNode {
|
||||
|
||||
public ListCommand() {
|
||||
super("list");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = ActionCommand.BotArgument.getBot(context);
|
||||
|
||||
CommandSender sender = context.getSender();
|
||||
List<AbstractBotAction<?>> actions = bot.getBotActions();
|
||||
if (actions.isEmpty()) {
|
||||
sender.sendMessage(text("This bot has no active actions", GRAY));
|
||||
return true;
|
||||
}
|
||||
|
||||
sender.sendMessage(
|
||||
asAdventure(bot.getDisplayName())
|
||||
.append(text("'s action list:", GRAY))
|
||||
);
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
AbstractBotAction<?> action = actions.get(i);
|
||||
sender.sendMessage(join(spaces(),
|
||||
text(i, GRAY),
|
||||
text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString())))
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.command.bot.subcommands.action;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.bot.agent.Actions;
|
||||
import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.LiteralNode;
|
||||
import org.leavesmc.leaves.command.WrappedArgument;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static io.papermc.paper.adventure.PaperAdventure.asAdventure;
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
import static net.kyori.adventure.text.event.HoverEvent.showText;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.AQUA;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
|
||||
import static org.leavesmc.leaves.command.bot.subcommands.ActionCommand.BotArgument.getBot;
|
||||
|
||||
public class StartCommand extends LiteralNode {
|
||||
|
||||
public StartCommand() {
|
||||
super("start");
|
||||
Actions.getAll()
|
||||
.stream()
|
||||
.map(this::actionNodeCreator)
|
||||
.forEach(this::children);
|
||||
}
|
||||
|
||||
private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotAction<?> action) throws CommandSyntaxException {
|
||||
ServerBot bot = getBot(context);
|
||||
CommandSender sender = context.getSender();
|
||||
|
||||
action.loadCommand(context);
|
||||
if (bot.addBotAction(action, sender)) {
|
||||
sender.sendMessage(join(spaces(),
|
||||
text("Action", GRAY),
|
||||
text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))),
|
||||
text("has been issued to", GRAY),
|
||||
asAdventure(bot.getDisplayName())
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
private @NotNull Supplier<LiteralNode> actionNodeCreator(AbstractBotAction<?> action) {
|
||||
return () -> new ActionLiteralNode(action);
|
||||
}
|
||||
|
||||
private class ActionLiteralNode extends LiteralNode {
|
||||
private final AbstractBotAction<?> action;
|
||||
|
||||
private 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 {
|
||||
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()) {
|
||||
builder = builder.executes(executor);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.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;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction;
|
||||
import org.leavesmc.leaves.command.ArgumentNode;
|
||||
import org.leavesmc.leaves.command.CommandContext;
|
||||
import org.leavesmc.leaves.command.LiteralNode;
|
||||
import org.leavesmc.leaves.command.bot.subcommands.ActionCommand;
|
||||
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static io.papermc.paper.adventure.PaperAdventure.asAdventure;
|
||||
import static net.kyori.adventure.text.Component.join;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.JoinConfiguration.spaces;
|
||||
import static net.kyori.adventure.text.event.HoverEvent.showText;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||
|
||||
public class StopCommand extends LiteralNode {
|
||||
|
||||
public StopCommand() {
|
||||
super("stop");
|
||||
children(StopIndexArgument::new);
|
||||
children(StopAll::new);
|
||||
}
|
||||
|
||||
private static class StopIndexArgument extends ArgumentNode<Integer> {
|
||||
|
||||
private StopIndexArgument() {
|
||||
super("index", IntegerArgumentType.integer(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<Suggestions> getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException {
|
||||
ServerBot bot = ActionCommand.BotArgument.getBot(context);
|
||||
|
||||
for (int i = 0; i < bot.getBotActions().size(); i++) {
|
||||
AbstractBotAction<?> action = bot.getBotActions().get(i);
|
||||
builder.suggest(String.valueOf(i), Component.literal(action.getName()));
|
||||
}
|
||||
|
||||
return builder.buildFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = ActionCommand.BotArgument.getBot(context);
|
||||
CommandSender sender = context.getSender();
|
||||
|
||||
int index = context.getArgument(StopIndexArgument.class);
|
||||
int maxIndex = bot.getBotActions().size() - 1;
|
||||
if (maxIndex < 0) {
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
|
||||
}
|
||||
if (index > maxIndex) {
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.integerTooHigh().create(index, maxIndex);
|
||||
}
|
||||
|
||||
AbstractBotAction<?> action = bot.getBotActions().get(index);
|
||||
BotActionStopEvent event = new BotActionStopEvent(
|
||||
bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender
|
||||
);
|
||||
event.callEvent();
|
||||
if (!event.isCancelled()) {
|
||||
action.stop(bot, BotActionStopEvent.Reason.COMMAND);
|
||||
bot.getBotActions().remove(index);
|
||||
sender.sendMessage(join(spaces(),
|
||||
text("Already stopped", GRAY),
|
||||
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
|
||||
text("action", GRAY),
|
||||
text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString())))
|
||||
));
|
||||
} else {
|
||||
sender.sendMessage(text("Action stop cancelled by a plugin", RED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StopAll extends LiteralNode {
|
||||
|
||||
private StopAll() {
|
||||
super("all");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||
ServerBot bot = ActionCommand.BotArgument.getBot(context);
|
||||
|
||||
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<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
|
||||
);
|
||||
event.callEvent();
|
||||
if (!event.isCancelled()) {
|
||||
forRemoval.add(action);
|
||||
action.stop(bot, BotActionStopEvent.Reason.COMMAND);
|
||||
} else {
|
||||
canceled.add(action);
|
||||
}
|
||||
}
|
||||
bot.getBotActions().removeAll(forRemoval);
|
||||
|
||||
if (canceled.isEmpty()) {
|
||||
sender.sendMessage(join(spaces(),
|
||||
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
|
||||
text("'s action list cleared", GRAY)
|
||||
));
|
||||
} else {
|
||||
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 (AbstractBotAction<?> action : canceled) {
|
||||
context.getSender().sendMessage(
|
||||
text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString())))
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,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;
|
||||
@@ -57,13 +57,17 @@ public class CraftBot extends CraftPlayer implements Bot {
|
||||
|
||||
@Override
|
||||
public <T extends BotAction<T>> void addAction(@NotNull T action) {
|
||||
switch (action) {
|
||||
case CraftBotAction act -> this.getHandle().addBotAction(act.getHandle(), null);
|
||||
default ->
|
||||
throw new IllegalArgumentException("Action " + action.getClass().getName() + " is not a valid BotAction type!");
|
||||
if (action instanceof CraftBotAction<?, ?> act) {
|
||||
this.getHandle().addBotAction(act.getHandle(), null);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Action " + action.getClass().getName() + " is not a valid BotAction type!");
|
||||
}
|
||||
}
|
||||
|
||||
public void addAction(@NotNull AbstractBotAction<?> action) {
|
||||
this.getHandle().addBotAction(action, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BotAction<?> getAction(int index) {
|
||||
return (BotAction<?>) this.getHandle().getBotActions().get(index).asCraft();
|
||||
@@ -81,15 +85,14 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(boolean save) {
|
||||
BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save);
|
||||
return true;
|
||||
return BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,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;
|
||||
|
||||
@@ -72,7 +72,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 {
|
||||
|
||||
+3
-3
@@ -19,14 +19,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;
|
||||
@@ -40,7 +40,7 @@ public abstract class CraftBotAction<T extends BotAction<T>, S extends ServerBot
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public ServerBotAction<?> getHandle() {
|
||||
public AbstractBotAction<?> getHandle() {
|
||||
return serverAction;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -17,12 +17,12 @@
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user