diff --git a/build.gradle b/build.gradle index b3f35803..2809708c 100644 --- a/build.gradle +++ b/build.gradle @@ -3,14 +3,13 @@ plugins { id 'maven-publish' } -apply plugin: 'maven-publish' - allprojects { - group = 'com.wizardlybump17.wlib' - version = '1.6.7' - apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'java' + apply plugin: 'maven-publish' + + group = 'com.wizardlybump17.wlib' + version = '1.6.7-ncs-2' repositories { mavenLocal() @@ -24,6 +23,10 @@ allprojects { compileJava { options.encoding = 'UTF-8' } + + assemble { + dependsOn(shadowJar) + } } java { @@ -32,8 +35,6 @@ allprojects { } subprojects { - apply plugin: 'maven-publish' - if (project.name == 'versions' || project.name.matches('v\\d_\\d+_R\\d+')) { tasks.withType(PublishToMavenRepository).configureEach { it.enabled = false @@ -79,8 +80,4 @@ subprojects { events "passed", "skipped", "failed", "standardOut", "standardError" } } - - build { - dependsOn(test, shadowJar) - } } \ No newline at end of file diff --git a/bukkit-utils/build.gradle b/bukkit-utils/build.gradle index 00e702b8..970dd5b2 100644 --- a/bukkit-utils/build.gradle +++ b/bukkit-utils/build.gradle @@ -4,6 +4,9 @@ dependencies { 'org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT', 'org.jetbrains:annotations:23.0.0', ) + compileOnly("net.kyori:adventure-api:4.18.0") + compileOnly("net.kyori:adventure-text-minimessage:4.18.0") + compileOnly("net.kyori:adventure-platform-bukkit:4.3.4") implementation( project(':utils') ) diff --git a/bukkit-utils/src/main/java/com/wizardlybump17/wlib/util/bukkit/MiniMessageUtil.java b/bukkit-utils/src/main/java/com/wizardlybump17/wlib/util/bukkit/MiniMessageUtil.java new file mode 100644 index 00000000..6cbc701a --- /dev/null +++ b/bukkit-utils/src/main/java/com/wizardlybump17/wlib/util/bukkit/MiniMessageUtil.java @@ -0,0 +1,39 @@ +package com.wizardlybump17.wlib.util.bukkit; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.Tag; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public final class MiniMessageUtil { + + private MiniMessageUtil() { + } + + public static @NotNull Component getMessage(@NotNull String message, @NotNull Map placeholders) { + MiniMessage miniMessage = MiniMessage.miniMessage(); + if (placeholders.isEmpty()) + return miniMessage.deserialize(message); + + TagResolver[] resolvers = new TagResolver[placeholders.size()]; + int resolverIndex = 0; + for (Map.Entry entry : placeholders.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + resolvers[resolverIndex++] = TagResolver.builder() + .tag( + key, + Tag.inserting(value instanceof Component component ? component : Component.text(String.valueOf(value))) + ) + .build(); + } + return miniMessage.deserialize(message, resolvers); + } + + public static @NotNull Component getMessage(@NotNull String message) { + return getMessage(message, Map.of()); + } +} diff --git a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandExecutor.java b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandExecutor.java index 57ed1875..cca749bd 100644 --- a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandExecutor.java +++ b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandExecutor.java @@ -1,13 +1,13 @@ package com.wizardlybump17.wlib.bungee.command; -import com.wizardlybump17.wlib.bungee.command.sender.GenericSender; -import com.wizardlybump17.wlib.bungee.command.sender.ProxiedPlayerSender; +import com.wizardlybump17.wlib.bungee.command.sender.BungeeCommandSender; import com.wizardlybump17.wlib.command.CommandManager; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.exception.CommandException; import com.wizardlybump17.wlib.command.holder.CommandExecutor; -import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.plugin.Command; +import java.util.logging.Level; + public class BungeeCommandExecutor extends Command implements CommandExecutor { private final CommandManager manager; @@ -18,17 +18,16 @@ public BungeeCommandExecutor(CommandManager manager, String name) { } @Override - public void execute(CommandSender sender, String commandName, String[] args) { + public void execute(com.wizardlybump17.wlib.command.sender.CommandSender sender, String commandName, String[] args) throws CommandException { manager.execute(sender, commandName + " " + String.join(" ", args)); } @Override public void execute(net.md_5.bungee.api.CommandSender sender, String[] args) { - CommandSender realSender; - if (sender instanceof ProxiedPlayer) - realSender = new ProxiedPlayerSender((ProxiedPlayer) sender); - else - realSender = new GenericSender(sender); - execute(realSender, getName(), args); + try { + execute(new BungeeCommandSender(sender), getName(), args); + } catch (CommandException e) { + manager.getHolder().getLogger().log(Level.SEVERE, "Error while executing a command", e); + } } } diff --git a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandManager.java b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandManager.java index 48c0b047..bfd1bafa 100644 --- a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandManager.java +++ b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/BungeeCommandManager.java @@ -1,9 +1,10 @@ package com.wizardlybump17.wlib.bungee.command; import com.wizardlybump17.wlib.command.CommandManager; -import com.wizardlybump17.wlib.command.RegisteredCommand; +import com.wizardlybump17.wlib.command.registered.RegisteredCommand; import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Plugin; +import org.jetbrains.annotations.NotNull; public class BungeeCommandManager extends CommandManager { @@ -12,7 +13,7 @@ public BungeeCommandManager(BungeeCommandHolder holder) { } @Override - public void registerCommands(Object... objects) { + public void registerCommands(@NotNull Object @NotNull ... objects) { super.registerCommands(objects); for (Object object : objects) { for (RegisteredCommand command : getCommands(object)) { diff --git a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/GenericSender.java b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/BungeeCommandSender.java similarity index 57% rename from bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/GenericSender.java rename to bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/BungeeCommandSender.java index 86698b06..702f31eb 100644 --- a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/GenericSender.java +++ b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/BungeeCommandSender.java @@ -1,11 +1,15 @@ package com.wizardlybump17.wlib.bungee.command.sender; -import com.wizardlybump17.wlib.command.CommandSender; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.connection.ConnectedPlayer; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; @RequiredArgsConstructor -public class GenericSender implements CommandSender { +public class BungeeCommandSender implements com.wizardlybump17.wlib.command.sender.CommandSender { private final net.md_5.bungee.api.CommandSender handle; @@ -34,12 +38,16 @@ public boolean hasPermission(String permission) { return handle.hasPermission(permission); } - @Override - public GenericSender toGeneric() { - return this; + public @NotNull ProxiedPlayer asProxiedPlayer() { + return (ProxiedPlayer) handle; } - public static boolean isGeneric() { - return true; + public @NotNull ConnectedPlayer asConnectedPlayer() { + return (ConnectedPlayer) handle; + } + + @Override + public boolean hasId(@NotNull UUID id) { + return handle instanceof ProxiedPlayer player && player.getUniqueId().equals(id); } } diff --git a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/ProxiedPlayerSender.java b/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/ProxiedPlayerSender.java deleted file mode 100644 index d2fca3f7..00000000 --- a/bungee/src/main/java/com/wizardlybump17/wlib/bungee/command/sender/ProxiedPlayerSender.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.wizardlybump17.wlib.bungee.command.sender; - -import com.wizardlybump17.wlib.command.CommandSender; -import lombok.RequiredArgsConstructor; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.ProxiedPlayer; - -@RequiredArgsConstructor -public class ProxiedPlayerSender implements CommandSender { - - private final ProxiedPlayer handle; - - @Override - public ProxiedPlayer getHandle() { - return handle; - } - - @Override - public void sendMessage(String message) { - handle.sendMessage(TextComponent.fromLegacyText(message)); - } - - @Override - public void sendMessage(String... messages) { - handle.sendMessage(TextComponent.fromLegacyText(String.join("\n", messages))); - } - - @Override - public String getName() { - return handle.getName(); - } - - @Override - public boolean hasPermission(String permission) { - return handle.hasPermission(permission); - } - - @Override - public GenericSender toGeneric() { - return new GenericSender(handle); - } -} diff --git a/commands/build.gradle b/commands/build.gradle index f57b9327..2497418c 100644 --- a/commands/build.gradle +++ b/commands/build.gradle @@ -11,6 +11,7 @@ dependencies { implementation("com.github.sisyphsu:dateparser:1.0.11") { exclude(group: "org.projectlombok", module: "lombok") } + testCompileOnly("org.jetbrains:annotations:26.0.1") } shadowJar { diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/CommandManager.java b/commands/src/main/java/com/wizardlybump17/wlib/command/CommandManager.java index 371354f6..08bff110 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/CommandManager.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/CommandManager.java @@ -1,82 +1,81 @@ package com.wizardlybump17.wlib.command; +import com.wizardlybump17.wlib.command.data.CommandData; +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.extractor.CommandExtractor; +import com.wizardlybump17.wlib.command.extractor.DirectCommandExtractor; +import com.wizardlybump17.wlib.command.extractor.MethodCommandExtractor; import com.wizardlybump17.wlib.command.holder.CommandHolder; -import com.wizardlybump17.wlib.util.ReflectionUtil; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.Nullable; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -@Getter -@RequiredArgsConstructor +import com.wizardlybump17.wlib.command.registered.RegisteredCommand; +import com.wizardlybump17.wlib.command.sender.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + public class CommandManager { - private final List commands = new ArrayList<>(); - protected final CommandHolder holder; - private final @NonNull Map, Map> fieldCache = new HashMap<>(); - - public void registerCommands(Object... objects) { - for (Object object : objects) { - for (Method method : object.getClass().getDeclaredMethods()) { - if (!method.isAnnotationPresent(Command.class) || method.getParameterCount() == 0 || !CommandSender.class.isAssignableFrom(method.getParameterTypes()[0])) - continue; - - MethodHandle handle; - try { - handle = MethodHandles.publicLookup().findVirtual(object.getClass(), method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes())); - } catch (NoSuchMethodException | IllegalAccessException e) { - holder.getLogger().log(Level.SEVERE, "Error while trying to get the MethodHandle for " + method.getName() + " at " + object.getClass().getName(), e); - continue; - } + private final @NotNull Map> commands = new HashMap<>(); + protected final @NotNull CommandHolder holder; + private final @NotNull Set commandExtractors = new HashSet<>(); - RegisteredCommand command = new RegisteredCommand( - method.getAnnotation(Command.class), - object, - method, - handle - ); - - commands.add(command); - com.wizardlybump17.wlib.command.holder.Command holderCommand = holder.getCommand(command.getName()); - if (holderCommand != null) - holderCommand.setExecutor(holderCommand.getDefaultExecutor(this, command.getName())); - } - } + public CommandManager(@NotNull CommandHolder holder) { + this.holder = holder; + commandExtractors.add(new MethodCommandExtractor()); + commandExtractors.add(new DirectCommandExtractor()); + } + public void registerCommands(@NotNull Object @NotNull ... objects) { + for (Object object : objects) + for (CommandExtractor extractor : commandExtractors) + registerCommands(extractor.extract(this, holder, object)); + } + + public void registerCommands(@NotNull Collection commands) { + commands.forEach(this::registerCommand); + } + + public void registerCommand(@NotNull RegisteredCommand command) { + command.onRegister(this); + List commands = this.commands.computeIfAbsent(command.getName().toLowerCase(), $ -> new ArrayList<>()); + commands.add(command); commands.sort(null); } public void unregisterCommands() { + commands.forEach((name, commands) -> { + commands.forEach(command -> command.onUnregister(this)); + commands.clear(); + }); commands.clear(); } - public void execute(CommandSender sender, String string) { + public void execute(@NotNull CommandSender sender, @NotNull String string) throws CommandException { if (commands.isEmpty()) return; - for (RegisteredCommand registeredCommand : commands) { - Command command = registeredCommand.getCommand(); + int spaceIndex = string.indexOf(' '); + String name; + if (spaceIndex == -1) + name = string; + else + name = string.substring(0, spaceIndex); + + for (RegisteredCommand registeredCommand : commands.getOrDefault(name, List.of())) { + CommandData command = registeredCommand.getCommand(); CommandResult result = registeredCommand.execute(sender, string); switch (result) { case PERMISSION_FAIL -> { - handleMessage(registeredCommand, sender, command.permissionMessage(), command.permissionMessageIsField()); + String message = command.getPermissionMessage(); + if (message != null) + sender.sendMessage(message); return; } case INVALID_SENDER -> { - handleMessage(registeredCommand, sender, command.invalidSenderMessage(), command.invalidSenderMessageIsField()); + String message = command.getInvalidSenderMessage(); + if (message != null) + sender.sendMessage(message); return; } @@ -87,55 +86,45 @@ public void execute(CommandSender sender, String string) { } } - protected void handleMessage(@NonNull RegisteredCommand registeredCommand, @NonNull CommandSender sender, @NonNull String message, boolean isField) { - if (!isField) { - if (!message.isEmpty()) - sender.sendMessage(message); - return; - } + public @NotNull List<@NotNull String> autoComplete(@NotNull CommandSender sender, @NotNull String string) { + return List.of(); + } - String fieldMessage = getFieldMessage(registeredCommand, message); - if (fieldMessage != null) - sender.sendMessage(fieldMessage); + public @NotNull List getCommands(@NotNull String name) { + List commands = this.commands.get(name); + return commands == null ? List.of() : List.copyOf(commands); } - protected @Nullable String getFieldMessage(@NonNull RegisteredCommand registeredCommand, @NonNull String fieldName) { - Map fields = fieldCache.computeIfAbsent(registeredCommand.getObject().getClass(), clazz -> { - Map map = new HashMap<>(); - for (Field field : clazz.getDeclaredFields()) - map.put(field.getName(), field); - return map; - }); + public @NotNull List getCommands(@NotNull Object object) { + List result = new ArrayList<>(commands.size()); + for (List commands : this.commands.values()) + for (RegisteredCommand command : commands) + if (command.isOwnedBy(object)) + result.add(command); + return result; + } - Field field = fields.get(fieldName); - if (field == null) - return null; + public @NotNull CommandHolder getHolder() { + return holder; + } - Object fieldValue = ReflectionUtil.getFieldValue(field, registeredCommand.getObject()); - return fieldValue == null ? null : fieldValue.toString(); + public @NotNull Map> getCommands() { + return Map.copyOf(commands); } - @NonNull - public List<@NonNull String> autoComplete(@NonNull CommandSender sender, @NonNull String string) { - List result = new ArrayList<>(); - for (RegisteredCommand command : commands) - result.addAll(command.autoComplete(sender, string)); - return result; + public @NotNull Set getCommandExtractors() { + return Set.copyOf(commandExtractors); + } + + public void addCommandExtractor(@NotNull CommandExtractor extractor) { + commandExtractors.add(extractor); } - public List getCommand(String name) { - List commands = new ArrayList<>(this.commands.size()); - for (RegisteredCommand command : this.commands) - if (command.getName().equalsIgnoreCase(name)) - commands.add(command); - return commands; + public void removeCommandExtractor(@NotNull CommandExtractor extractor) { + commandExtractors.remove(extractor); } - public List getCommands(Object object) { - List commands = new ArrayList<>(this.commands.size()); - for (RegisteredCommand command : this.commands) - if (command.getObject() == object) - commands.add(command); - return commands; + public boolean hasCommandExtractor(@NotNull CommandExtractor extractor) { + return commandExtractors.contains(extractor); } } \ No newline at end of file diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/RegisteredCommand.java b/commands/src/main/java/com/wizardlybump17/wlib/command/RegisteredCommand.java deleted file mode 100644 index 5ae2885e..00000000 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/RegisteredCommand.java +++ /dev/null @@ -1,275 +0,0 @@ -package com.wizardlybump17.wlib.command; - -import com.wizardlybump17.wlib.command.args.ArgsNode; -import com.wizardlybump17.wlib.command.args.ArgsReaderRegistry; -import com.wizardlybump17.wlib.command.args.ArgsReaderType; -import com.wizardlybump17.wlib.command.args.reader.ArgsReader; -import com.wizardlybump17.wlib.command.args.reader.ArgsReaderException; -import com.wizardlybump17.wlib.object.Pair; -import lombok.Getter; -import lombok.NonNull; -import org.jetbrains.annotations.NotNull; - -import java.lang.invoke.MethodHandle; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.*; - -@Getter -public class RegisteredCommand implements Comparable { - - private final Command command; - private final Object object; - private final Method method; - private final List nodes = new ArrayList<>(); - private final @NonNull MethodHandle methodHandle; - - public RegisteredCommand(Command command, Object object, Method method, @NonNull MethodHandle methodHandle) { - this.command = command; - this.object = object; - this.method = method; - this.methodHandle = methodHandle; - prepareNodes(); - } - - private void prepareNodes() { - String[] commandArgs = command.execution().split(" "); - - Class[] types = method.getParameterTypes(); - Parameter[] parameters = method.getParameters(); - int index = 1; //skipping the first type because of the CommandSender - for (String commandArg : commandArgs) { - if (!requiredArgs(commandArg)) { - nodes.add(new ArgsNode( - commandArg, - false, - null, - null, - false - )); - continue; - } - - Description description = parameters[index].getAnnotation(Description.class); - - ArgsReaderType argsReaderType = parameters[index].getAnnotation(ArgsReaderType.class); - if (argsReaderType == null && Argument.class.isAssignableFrom(types[index])) - throw new IllegalArgumentException("the \"" + commandArg + "\" argument requires the " + ArgsReaderType.class.getName() + " annotation"); - - ArgsReader reader; - if (argsReaderType == null) - reader = ArgsReaderRegistry.INSTANCE.getReader(types[index]); - else - reader = ArgsReaderRegistry.INSTANCE.get(argsReaderType.value()); - if (reader == null) - throw new IllegalArgumentException("no reader found for " + types[index].getName()); - - nodes.add(new ArgsNode( - trim(commandArg), - true, - reader, - description == null ? null : description.value(), - Argument.class.isAssignableFrom(types[index]) - )); - - index++; - } - } - - public String getName() { - return command.execution().split(" ")[0]; - } - - @Override - public int compareTo(@NotNull RegisteredCommand o) { - if (o.command.priority() == -1 && command.priority() == -1) { - int args = compareArgs(o); - - if (args == 0) - return compareSize(o); - - return args; - } - - return Integer.compare(o.command.priority(), command.priority()); - } - - private int compareArgs(RegisteredCommand other) { - return Integer.compare(other.command.execution().split(" ").length, command.execution().split(" ").length); - } - - private int compareSize(RegisteredCommand other) { - return Integer.compare(other.command.execution().length(), command.execution().length()); - } - - public Optional>> parse(String input, boolean autoComplete) throws ArgsReaderException { - List toParse = new ArrayList<>(); - checkArrays(input, toParse, autoComplete); - - List> result = new ArrayList<>(nodes.size()); - - if (parseRequiredOnly(result, toParse, autoComplete)) - return Optional.of(result); - - return Optional.empty(); - } - - private boolean parseRequiredOnly(List> target, List strings, boolean autoComplete) throws ArgsReaderException { - if (autoComplete && nodes.size() > strings.size()) - return false; - - for (int i = 0; i < nodes.size() && i < strings.size(); i++) { - ArgsNode node = nodes.get(i); - if (!node.isUserInput()) { - if (!node.getName().equalsIgnoreCase(strings.get(i))) - return false; - - continue; - } - - Object parse = node.parse(strings.get(i)); - if (parse == ArgsNode.EMPTY) - continue; - - target.add(new Pair<>(node, parse)); - } - - return true; - } - - private void checkArrays(String input, List target, boolean autoComplete) throws ArgsReaderException { - StringBuilder builder = new StringBuilder(); - boolean inArray = false; - for (String s : input.split(" ")) { - if (s.startsWith("\"") && s.endsWith("\"") && !s.endsWith("\\\"") && s.length() != 1) { //"string" | single word - target.add(s.substring(1, s.length() - 1)); - continue; - } - - if (s.startsWith("\"")) { //"string | it is starting the array - builder.append(s.substring(1).replace("\\\"", "\"")).append(" "); - inArray = true; - continue; - } - - if (s.endsWith("\"") && !s.endsWith("\\\"")) { //string" | it is ending the array - builder.append(s.replace("\\\"", "\""), 0, s.length() - 1); - target.add(builder.toString()); - builder = new StringBuilder(); - inArray = false; - continue; - } - - if (!builder.isEmpty()) { //string | it is in the array - builder.append(s.replace("\\\"", "\"")).append(" "); - continue; - } - - target.add(s.replace("\\\"", "\"")); //string | it is not in the array - } - - if (inArray && !autoComplete) - throw new ArgsReaderException("Invalid array"); - } - - public CommandResult execute(CommandSender sender, String string) { - try { - Optional>> parse = parse(string, true); - if (parse.isEmpty()) - return CommandResult.ARGS_FAIL; - - if (!getSenderType().isInstance(sender) && !isSenderGeneric()) - return CommandResult.INVALID_SENDER; - - Object[] objects = parse.get().stream().map(Pair::getSecond).toArray(); - return executeInternal(sender, objects); - } catch (ArgsReaderException e) { - return CommandResult.EXCEPTION; - } - } - - private CommandResult executeInternal(CommandSender sender, Object[] objects) { - try { - if (!command.permission().isEmpty() && !sender.hasPermission(command.permission())) - return CommandResult.PERMISSION_FAIL; - - List list = new ArrayList<>(Arrays.asList(objects)); - list.add(0, isSenderGeneric() ? sender.toGeneric() : sender); - - if (list.size() != method.getParameterCount()) - return CommandResult.ARGS_FAIL; - - list.add(0, object); - methodHandle.invokeWithArguments(list); - return CommandResult.SUCCESS; - } catch (Throwable e) { - e.printStackTrace(); - return CommandResult.METHOD_FAIL; - } - } - - @NonNull - public List<@NonNull String> autoComplete(@NonNull CommandSender sender, @NonNull String string) { - if (nodes.size() == 1) - return Collections.emptyList(); - - if (!getSenderType().isInstance(sender) && !isSenderGeneric()) - return Collections.emptyList(); - - try { - Optional>> parse = parse(string, false); - if (parse.isEmpty()) - return Collections.emptyList(); - - String[] split = string.split(" "); - String lastString = split[split.length - 1]; - - List> pairs = parse.get(); - - if (pairs.isEmpty()) { - ArgsNode secondNode = nodes.get(1); - ArgsReader secondNodeReader = secondNode.getReader(); - return secondNodeReader == null ? List.of(secondNode.getName()) : secondNodeReader.autoComplete(sender, lastString); - } - - Pair lastPair = pairs.get(pairs.size() - 1); - - ArgsNode node = lastPair.getFirst(); - ArgsReader reader = node.getReader(); - - return reader == null ? List.of(node.getName()) : reader.autoComplete(sender, lastString); - } catch (ArgsReaderException e) { - e.printStackTrace(); - return Collections.emptyList(); - } - } - - @Override - public String toString() { - return "RegisteredCommand{" + command.execution() + "}"; - } - - @SuppressWarnings("unchecked") - public Class> getSenderType() { - return (Class>) method.getParameterTypes()[0]; - } - - public boolean isSenderGeneric() { - boolean result = false; - try { - result = (Boolean) getSenderType().getDeclaredMethod("isGeneric").invoke(null); - } catch (NoSuchMethodException ignored) { - } catch (Exception e) { - e.printStackTrace(); - } - return result; - } - - private static String trim(String string) { - return string.substring(1, string.length() - 1); - } - - private static boolean requiredArgs(String string) { - return string.startsWith("<") && string.endsWith(">"); - } -} \ No newline at end of file diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/Command.java b/commands/src/main/java/com/wizardlybump17/wlib/command/annotation/Command.java similarity index 90% rename from commands/src/main/java/com/wizardlybump17/wlib/command/Command.java rename to commands/src/main/java/com/wizardlybump17/wlib/command/annotation/Command.java index ca53cf22..b941b23b 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/Command.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/annotation/Command.java @@ -1,4 +1,7 @@ -package com.wizardlybump17.wlib.command; +package com.wizardlybump17.wlib.command.annotation; + +import com.wizardlybump17.wlib.command.sender.CommandSender; +import org.jetbrains.annotations.NotNull; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -81,4 +84,9 @@ * @return if the {@link #invalidSenderMessage()} is a field in the class that have this annotation */ boolean invalidSenderMessageIsField() default false; + + /** + * @return the type of the {@link CommandSender#getHandle()} that can execute this command + */ + @NotNull Class senderType() default Object.class; } diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/ArgsNode.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/ArgsNode.java index afb04352..23d07d47 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/ArgsNode.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/ArgsNode.java @@ -42,4 +42,16 @@ public Object parse(String input) throws ArgsReaderException { return object; } + + public static @NotNull ArgsNode literal(@NotNull String string) { + return new ArgsNode(string, false, null, null, false); + } + + public static @NotNull ArgsNode userInput(@NotNull String name, @NotNull ArgsReader reader) { + return new ArgsNode(name, true, reader, null, false); + } + + public static @NotNull ArgsNode userInput(@NotNull String name, @NotNull Class type) { + return userInput(name, ArgsReaderRegistry.INSTANCE.getReader(type)); + } } diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ArgsReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ArgsReader.java index 3ca7ecee..d8a6fa5a 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ArgsReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ArgsReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.jetbrains.annotations.Nullable; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/BooleanReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/BooleanReader.java index ef854c6a..539558be 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/BooleanReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/BooleanReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ByteReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ByteReader.java index 6b7e920d..00c9056c 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ByteReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ByteReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/DoubleReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/DoubleReader.java index 9dd12592..b7c4f356 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/DoubleReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/DoubleReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/FloatReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/FloatReader.java index 1541cf68..f90a346a 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/FloatReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/FloatReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/IntegerReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/IntegerReader.java index 111c3c09..5123f358 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/IntegerReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/IntegerReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ShortReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ShortReader.java index af95f3ff..14e84005 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ShortReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/ShortReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/StringReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/StringReader.java index e6719a67..93f2c9c4 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/StringReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/StringReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/UUIDReader.java b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/UUIDReader.java index d061710b..d9f4c7db 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/UUIDReader.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/args/reader/UUIDReader.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.args.reader; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/completer/ArgumentCompleter.java b/commands/src/main/java/com/wizardlybump17/wlib/command/completer/ArgumentCompleter.java index 187191c0..f0145c0d 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/completer/ArgumentCompleter.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/completer/ArgumentCompleter.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.completer; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/data/AnnotationCommandData.java b/commands/src/main/java/com/wizardlybump17/wlib/command/data/AnnotationCommandData.java new file mode 100644 index 00000000..e45d26f0 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/data/AnnotationCommandData.java @@ -0,0 +1,100 @@ +package com.wizardlybump17.wlib.command.data; + +import com.wizardlybump17.wlib.command.annotation.Command; +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class AnnotationCommandData extends CommandData { + + private final @NotNull Command annotation; + private final @NotNull Object object; + private final @NotNull Map fieldCache = new HashMap<>(); + + public AnnotationCommandData(@NotNull Command annotation, @NotNull Object object) { + this.annotation = annotation; + this.object = object; + } + + @Override + public @NotNull String getExecution() { + return annotation.execution(); + } + + @Override + public @Nullable String getPermission() { + String permission = annotation.permission(); + return permission.isBlank() ? super.getPermission() : permission; + } + + @Override + public @Nullable String getPermissionMessage() { + return getMessage(annotation.permissionMessage(), annotation.permissionMessageIsField(), super.getPermissionMessage()); + } + + @Override + public int getPriority() { + int priority = annotation.priority(); + return priority == -1 ? super.getPriority() : priority; + } + + @Override + public @Nullable String getDescription() { + String description = annotation.description(); + return description.isBlank() ? super.getDescription() : description; + } + + @Override + public @Nullable String getInvalidSenderMessage() { + return getMessage(annotation.invalidSenderMessage(), annotation.invalidSenderMessageIsField(), super.getInvalidSenderMessage()); + } + + protected @Nullable String getMessage(@NotNull String message, boolean isField, @Nullable String defaultMessage) { + if (isField) { + return ReflectionUtil.getFieldValue( + fieldCache.computeIfAbsent( + message, + $ -> ReflectionUtil.getField(message, object.getClass()) + ), + object + ); + } + return message.isBlank() ? defaultMessage : message; + } + + public @NotNull Command getAnnotation() { + return annotation; + } + + @Override + public @NotNull Class getSenderType() { + return annotation.senderType(); + } + + @Override + public boolean equals(Object object1) { + if (object1 == null || getClass() != object1.getClass()) + return false; + AnnotationCommandData that = (AnnotationCommandData) object1; + return Objects.equals(annotation, that.annotation) && Objects.equals(object, that.object) && Objects.equals(fieldCache, that.fieldCache); + } + + @Override + public int hashCode() { + return Objects.hash(annotation, object, fieldCache); + } + + @Override + public String toString() { + return "AnnotationCommandData{" + + "annotation=" + annotation + + ", object=" + object + + ", fieldCache=" + fieldCache + + '}'; + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/data/CommandData.java b/commands/src/main/java/com/wizardlybump17/wlib/command/data/CommandData.java new file mode 100644 index 00000000..9dd74ef5 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/data/CommandData.java @@ -0,0 +1,81 @@ +package com.wizardlybump17.wlib.command.data; + +import com.wizardlybump17.wlib.command.sender.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class CommandData { + + /** + *

How the sender must type the command in order for it to be triggered. + * Example:

command hello world
+ * In the example above, the sender must type /command hello world, so it can be triggered. + * To add parameters that depends on the sender input, just put the parameter between <>. + *
+ * Example:
command <hello> world

+ *

The type of each parameter is defined in the method that have this annotation. + * An example for the command above: + *

+     *  @Command(execution = "command <hello> world")
+     *  public void commandHelloWorld(GenericSender sender, String hello) {
+     *      System.out.println(sender.getName() + " executed the hello world command with the argument " + hello);
+     *  }
+     * 

+ * + * @return how the command must be sent to be triggered + * @see com.wizardlybump17.wlib.command.args.reader.ArgsReader + */ + public abstract @NotNull String getExecution(); + + /** + * @return which permission the sender must have to trigger this command + */ + public @Nullable String getPermission() { + return null; + } + + /** + *

Used when the {@link CommandSender} does not have the required {@link #getPermission()}.

+ * @return the message to be sent when the {@link CommandSender} does not have the required {@link #getPermission()} + */ + public @Nullable String getPermissionMessage() { + return null; + } + + /** + * @return the priority of this command + */ + public int getPriority() { + return getExecution().split(" ").length; + } + + /** + * @return the description of this command + */ + public @Nullable String getDescription() { + return null; + } + + /** + *

Used when the {@link CommandSender} is not valid for this command.

+ * @return the message to be sent when the {@link CommandSender} is not valid for this command + */ + public @Nullable String getInvalidSenderMessage() { + return null; + } + + public final @NotNull String getName() { + return getExecution().split(" ")[0]; + } + + /** + * @return the {@link CommandSender#getHandle()} that can execute this command + */ + public @NotNull Class getSenderType() { + return Object.class; + } + + public static @NotNull SimpleCommandData.Builder builder() { + return new SimpleCommandData.Builder(); + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/data/SimpleCommandData.java b/commands/src/main/java/com/wizardlybump17/wlib/command/data/SimpleCommandData.java new file mode 100644 index 00000000..66905c05 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/data/SimpleCommandData.java @@ -0,0 +1,216 @@ +package com.wizardlybump17.wlib.command.data; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public class SimpleCommandData extends CommandData { + + private final @NotNull Supplier execution; + private final @NotNull Supplier permission; + private final @NotNull Supplier permissionMessage; + private final @NotNull Supplier priority; + private final @NotNull Supplier description; + private final @NotNull Supplier invalidSenderMessage; + private final @NotNull Supplier> senderType; + + public SimpleCommandData(@NotNull Supplier execution, @NotNull Supplier permission, @NotNull Supplier permissionMessage, @NotNull Supplier priority, @NotNull Supplier description, @NotNull Supplier invalidSenderMessage, @NotNull Supplier> senderType) { + this.execution = execution; + this.permission = permission; + this.permissionMessage = permissionMessage; + this.priority = priority; + this.description = description; + this.invalidSenderMessage = invalidSenderMessage; + this.senderType = senderType; + } + + public SimpleCommandData(@NotNull String execution, @Nullable String permission, @Nullable String permissionMessage, int priority, @Nullable String description, @Nullable String invalidSenderMessage, @NotNull Class senderType) { + this( + () -> execution, + () -> permission, + () -> permissionMessage, + () -> priority, + () -> description, + () -> invalidSenderMessage, + () -> senderType + ); + } + + @Override + public @NotNull String getExecution() { + return execution.get(); + } + + @Override + public @Nullable String getPermission() { + return permission.get(); + } + + @Override + public @Nullable String getPermissionMessage() { + return permissionMessage.get(); + } + + @Override + public int getPriority() { + return priority.get(); + } + + @Override + public @Nullable String getDescription() { + return description.get(); + } + + @Override + public @Nullable String getInvalidSenderMessage() { + return invalidSenderMessage.get(); + } + + @Override + public @NotNull Class getSenderType() { + return senderType.get(); + } + + public static class Builder { + + Builder() { + } + + private @Nullable Supplier execution; + private @Nullable Supplier permission; + private @Nullable Supplier permissionMessage; + private @Nullable Supplier priority; + private @Nullable Supplier description; + private @Nullable Supplier invalidSenderMessage; + private @Nullable Supplier> senderType; + + public @Nullable String execution() { + return execution == null ? null : execution.get(); + } + + public @NotNull Builder execution(@Nullable String execution) { + this.execution = () -> execution; + return this; + } + + public @NotNull Builder execution(@Nullable Supplier execution) { + this.execution = execution; + return this; + } + + public @Nullable String permission() { + return permission == null ? null : permission.get(); + } + + public @NotNull Builder permission(@Nullable String permission) { + this.permission = () -> permission; + return this; + } + + public @NotNull Builder permission(@Nullable Supplier permission) { + this.permission = permission; + return this; + } + + public @Nullable String permissionMessage() { + return permissionMessage == null ? null : permissionMessage.get(); + } + + public @NotNull Builder permissionMessage(@Nullable String permissionMessage) { + this.permissionMessage = () -> permissionMessage; + return this; + } + + public @NotNull Builder permissionMessage(@Nullable Supplier permissionMessage) { + this.permissionMessage = permissionMessage; + return this; + } + + public @Nullable Integer priority() { + return priority == null ? null : priority.get(); + } + + public @NotNull Builder priority(@Nullable Integer priority) { + this.priority = () -> priority; + return this; + } + + public @NotNull Builder priority(@Nullable Supplier priority) { + this.priority = priority; + return this; + } + + public @Nullable String description() { + return description == null ? null : description.get(); + } + + public @NotNull Builder description(@Nullable String description) { + this.description = () -> description; + return this; + } + + public @NotNull Builder description(@Nullable Supplier description) { + this.description = description; + return this; + } + + public @Nullable String invalidSenderMessage() { + return invalidSenderMessage == null ? null : invalidSenderMessage.get(); + } + + public @NotNull Builder invalidSenderMessage(@Nullable String invalidSenderMessage) { + this.invalidSenderMessage = () -> invalidSenderMessage; + return this; + } + + public @NotNull Builder invalidSenderMessage(@Nullable Supplier invalidSenderMessage) { + this.invalidSenderMessage = invalidSenderMessage; + return this; + } + + public @Nullable Class senderType() { + return senderType == null ? null : senderType.get(); + } + + public @NotNull Builder senderType(@Nullable Class senderType) { + this.senderType = () -> senderType; + return this; + } + + public @NotNull Builder senderType(@Nullable Supplier> senderType) { + this.senderType = senderType; + return this; + } + + public @NotNull CommandData build() { + String execution = execution(); + if (execution == null) + throw new NullPointerException("The execution can not be null"); + + String permission = permission(); + String permissionMessage = permissionMessage(); + + Integer priority = priority(); + if (priority == null) + priority = execution.split(" ").length; + + String description = description(); + String invalidSenderMessage = invalidSenderMessage(); + + Class senderType = senderType(); + if (senderType == null) + senderType = Object.class; + + return new SimpleCommandData( + execution, + permission, + permissionMessage, + priority, + description, + invalidSenderMessage, + senderType + ); + } + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/exception/CommandException.java b/commands/src/main/java/com/wizardlybump17/wlib/command/exception/CommandException.java new file mode 100644 index 00000000..7c99b73f --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/exception/CommandException.java @@ -0,0 +1,21 @@ +package com.wizardlybump17.wlib.command.exception; + +import org.jetbrains.annotations.NotNull; + +public class CommandException extends Exception { + + public CommandException() { + } + + public CommandException(@NotNull String message) { + super(message); + } + + public CommandException(@NotNull String message, @NotNull Throwable cause) { + super(message, cause); + } + + public CommandException(@NotNull Throwable cause) { + super(cause); + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/executor/CommandExecutor.java b/commands/src/main/java/com/wizardlybump17/wlib/command/executor/CommandExecutor.java new file mode 100644 index 00000000..a0c3720a --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/executor/CommandExecutor.java @@ -0,0 +1,12 @@ +package com.wizardlybump17.wlib.command.executor; + +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.sender.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public interface CommandExecutor { + + void execute(@NotNull CommandSender sender, @NotNull Map args) throws CommandException; +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/CommandExtractor.java b/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/CommandExtractor.java new file mode 100644 index 00000000..8f1d4373 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/CommandExtractor.java @@ -0,0 +1,13 @@ +package com.wizardlybump17.wlib.command.extractor; + +import com.wizardlybump17.wlib.command.CommandManager; +import com.wizardlybump17.wlib.command.holder.CommandHolder; +import com.wizardlybump17.wlib.command.registered.RegisteredCommand; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface CommandExtractor { + + @NotNull List extract(@NotNull CommandManager manager, @NotNull CommandHolder holder, @NotNull Object object); +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/DirectCommandExtractor.java b/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/DirectCommandExtractor.java new file mode 100644 index 00000000..bb21f6c5 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/DirectCommandExtractor.java @@ -0,0 +1,16 @@ +package com.wizardlybump17.wlib.command.extractor; + +import com.wizardlybump17.wlib.command.CommandManager; +import com.wizardlybump17.wlib.command.holder.CommandHolder; +import com.wizardlybump17.wlib.command.registered.RegisteredCommand; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class DirectCommandExtractor implements CommandExtractor { + + @Override + public @NotNull List extract(@NotNull CommandManager manager, @NotNull CommandHolder holder, @NotNull Object object) { + return object instanceof RegisteredCommand command ? List.of(command) : List.of(); + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/MethodCommandExtractor.java b/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/MethodCommandExtractor.java new file mode 100644 index 00000000..354da31d --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/extractor/MethodCommandExtractor.java @@ -0,0 +1,44 @@ +package com.wizardlybump17.wlib.command.extractor; + +import com.wizardlybump17.wlib.command.CommandManager; +import com.wizardlybump17.wlib.command.annotation.Command; +import com.wizardlybump17.wlib.command.holder.CommandHolder; +import com.wizardlybump17.wlib.command.registered.RegisteredCommand; +import com.wizardlybump17.wlib.command.registered.RegisteredMethodCommand; +import com.wizardlybump17.wlib.command.sender.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +public class MethodCommandExtractor implements CommandExtractor { + + @Override + public @NotNull List extract(@NotNull CommandManager manager, @NotNull CommandHolder holder, @NotNull Object object) { + List commands = new ArrayList<>(); + for (Method method : object.getClass().getDeclaredMethods()) { + if (!method.isAnnotationPresent(Command.class) || method.getParameterCount() == 0 || !CommandSender.class.isAssignableFrom(method.getParameterTypes()[0])) + continue; + + RegisteredMethodCommand command; + try { + command = new RegisteredMethodCommand( + method.getAnnotation(Command.class), + object, + method + ); + } catch (Exception e) { + holder.getLogger().log(Level.SEVERE, "Error while creating a command", e); + continue; + } + + commands.add(command); + com.wizardlybump17.wlib.command.holder.Command holderCommand = holder.getCommand(command.getName()); + if (holderCommand != null) + holderCommand.setExecutor(holderCommand.getDefaultExecutor(manager, command.getName())); + } + return commands; + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/holder/CommandExecutor.java b/commands/src/main/java/com/wizardlybump17/wlib/command/holder/CommandExecutor.java index de8e1475..05321945 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/holder/CommandExecutor.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/holder/CommandExecutor.java @@ -1,12 +1,13 @@ package com.wizardlybump17.wlib.command.holder; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReaderException; +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.sender.CommandSender; /** * Interface for intercepting commands when they are called */ public interface CommandExecutor { - void execute(CommandSender sender, String commandName, String[] args) throws ArgsReaderException; + void execute(CommandSender sender, String commandName, String[] args) throws ArgsReaderException, CommandException; } diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredCommand.java b/commands/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredCommand.java new file mode 100644 index 00000000..aa31aea1 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredCommand.java @@ -0,0 +1,138 @@ +package com.wizardlybump17.wlib.command.registered; + +import com.wizardlybump17.wlib.command.CommandManager; +import com.wizardlybump17.wlib.command.CommandResult; +import com.wizardlybump17.wlib.command.args.ArgsNode; +import com.wizardlybump17.wlib.command.args.reader.ArgsReaderException; +import com.wizardlybump17.wlib.command.data.CommandData; +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.executor.CommandExecutor; +import com.wizardlybump17.wlib.command.sender.CommandSender; +import com.wizardlybump17.wlib.util.StringUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Optional; + +public class RegisteredCommand implements Comparable { + + private final @NotNull CommandData command; + private final @NotNull List nodes; + private final @NotNull CommandExecutor executor; + + public RegisteredCommand(@NotNull CommandData command, @NotNull List nodes, @NotNull CommandExecutor executor) { + this.command = command; + this.nodes = nodes; + this.executor = executor; + } + + protected RegisteredCommand(@NotNull CommandData command, @NotNull List nodes) { + this.command = command; + this.nodes = nodes; + executor = createExecutor(); + } + + protected CommandExecutor createExecutor() { + throw new UnsupportedOperationException(); + } + + public String getName() { + return command.getExecution().split(" ")[0]; + } + + @Override + public int compareTo(@NotNull RegisteredCommand o) { + return Integer.compare(o.command.getPriority(), command.getPriority()); + } + + public Optional> parse(String input) throws ArgsReaderException { + List toParse = StringUtil.parseQuotedStrings(input); + + LinkedHashMap result = new LinkedHashMap<>(); + + if (checkNodes(result, toParse)) + return Optional.of(result); + + return Optional.empty(); + } + + protected boolean checkNodes(LinkedHashMap target, List strings) throws ArgsReaderException { + if (nodes.size() > strings.size()) + return false; + + for (int i = 0; i < nodes.size() && i < strings.size(); i++) { + ArgsNode node = nodes.get(i); + if (!node.isUserInput()) { + if (node.getName().equalsIgnoreCase(strings.get(i))) + continue; + return false; + } + + Object parse = node.parse(strings.get(i)); + if (parse != ArgsNode.EMPTY) + target.put(node.getName(), parse); + } + + return true; + } + + public @NotNull CommandResult execute(@NotNull CommandSender sender, @NotNull String string) throws CommandException { + if (!canExecute(sender)) + return CommandResult.INVALID_SENDER; + + String permission = command.getPermission(); + if (permission != null && !sender.hasPermission(permission)) + return CommandResult.PERMISSION_FAIL; + + try { + Optional> parse = parse(string); + if (parse.isEmpty()) + return CommandResult.ARGS_FAIL; + + LinkedHashMap args = parse.get(); + if (!isValidArgs(args)) + return CommandResult.ARGS_FAIL; + + executor.execute(sender, args); + return CommandResult.SUCCESS; + } catch (ArgsReaderException e) { + return CommandResult.EXCEPTION; + } + } + + protected boolean isValidArgs(@NotNull LinkedHashMap args) { + return true; + } + + public boolean canExecute(@NotNull CommandSender sender) { + return command.getSenderType().isInstance(sender.getHandle()); + } + + @Override + public String toString() { + return "RegisteredCommand{" + command.getExecution() + "}"; + } + + public @NotNull CommandData getCommand() { + return command; + } + + public @NotNull CommandExecutor getExecutor() { + return executor; + } + + public @NotNull List getNodes() { + return nodes; + } + + public boolean isOwnedBy(@NotNull Object object) { + return false; + } + + public void onRegister(@NotNull CommandManager manager) { + } + + public void onUnregister(@NotNull CommandManager manager) { + } +} \ No newline at end of file diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredMethodCommand.java b/commands/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredMethodCommand.java new file mode 100644 index 00000000..721860f0 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredMethodCommand.java @@ -0,0 +1,123 @@ +package com.wizardlybump17.wlib.command.registered; + +import com.wizardlybump17.wlib.command.Argument; +import com.wizardlybump17.wlib.command.Description; +import com.wizardlybump17.wlib.command.annotation.Command; +import com.wizardlybump17.wlib.command.args.ArgsNode; +import com.wizardlybump17.wlib.command.args.ArgsReaderRegistry; +import com.wizardlybump17.wlib.command.args.ArgsReaderType; +import com.wizardlybump17.wlib.command.args.reader.ArgsReader; +import com.wizardlybump17.wlib.command.data.AnnotationCommandData; +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.executor.CommandExecutor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +@Getter +public class RegisteredMethodCommand extends RegisteredCommand { + + private final @NotNull Command annotation; + private final @NotNull Object object; + private final @NotNull Method method; + private final @NotNull MethodHandle methodHandle; + + public RegisteredMethodCommand(@NotNull Command annotation, @NotNull Object object, @NotNull Method method) throws NoSuchMethodException, IllegalAccessException { + super( + new AnnotationCommandData( + annotation, + object + ), + new ArrayList<>() + ); + this.annotation = annotation; + this.object = object; + this.method = method; + methodHandle = MethodHandles.publicLookup().findVirtual(object.getClass(), method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes())); + prepareNodes(); + } + + @Override + protected CommandExecutor createExecutor() { + return (sender, args) -> { + List objects = new ArrayList<>(args.values()); + objects.add(0, object); + objects.add(1, sender); + try { + methodHandle.invokeWithArguments(objects); + } catch (Throwable e) { + throw new CommandException("Error while executing the command " + getCommand().getExecution() + " with the arguments " + args, e); + } + }; + } + + protected void prepareNodes() { + String[] commandArgs = getCommand().getExecution().split(" "); + + Class[] types = method.getParameterTypes(); + Parameter[] parameters = method.getParameters(); + int index = 1; //skipping the first type because of the CommandSender + for (String commandArg : commandArgs) { + if (!isRequiredArgs(commandArg)) { + getNodes().add(new ArgsNode( + commandArg, + false, + null, + null, + false + )); + continue; + } + + Description description = parameters[index].getAnnotation(Description.class); + + ArgsReaderType argsReaderType = parameters[index].getAnnotation(ArgsReaderType.class); + if (argsReaderType == null && Argument.class.isAssignableFrom(types[index])) + throw new IllegalArgumentException("the \"" + commandArg + "\" argument requires the " + ArgsReaderType.class.getName() + " annotation"); + + ArgsReader reader; + if (argsReaderType == null) + reader = ArgsReaderRegistry.INSTANCE.getReader(types[index]); + else + reader = ArgsReaderRegistry.INSTANCE.get(argsReaderType.value()); + if (reader == null) + throw new IllegalArgumentException("no reader found for " + types[index].getName()); + + getNodes().add(new ArgsNode( + trim(commandArg), + true, + reader, + description == null ? null : description.value(), + Argument.class.isAssignableFrom(types[index]) + )); + + index++; + } + } + + @Override + protected boolean isValidArgs(@NotNull LinkedHashMap args) { + return args.size() + 1 == method.getParameterCount(); + } + + @Override + public boolean isOwnedBy(@NotNull Object object) { + return this.object == object; + } + + private static String trim(String string) { + return string.substring(1, string.length() - 1); + } + + private static boolean isRequiredArgs(String string) { + return string.startsWith("<") && string.endsWith(">"); + } +} \ No newline at end of file diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/sender/BasicCommandSender.java b/commands/src/main/java/com/wizardlybump17/wlib/command/sender/BasicCommandSender.java new file mode 100644 index 00000000..8f2d8f86 --- /dev/null +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/sender/BasicCommandSender.java @@ -0,0 +1,164 @@ +package com.wizardlybump17.wlib.command.sender; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class BasicCommandSender implements CommandSender { + + private final @NotNull S handle; + private final @NotNull String name; + private final @NotNull UUID id; + private final @NotNull Consumer messageConsumer; + private final @NotNull Predicate permissionTest; + + public BasicCommandSender(@NotNull S handle, @NotNull String name, @NotNull UUID id, @NotNull Consumer messageConsumer, @NotNull Predicate permissionTest) { + this.handle = handle; + this.name = name; + this.id = id; + this.messageConsumer = messageConsumer; + this.permissionTest = permissionTest; + } + + @Override + public @NotNull S getHandle() { + return handle; + } + + @Override + public void sendMessage(String message) { + messageConsumer.accept(message); + } + + @Override + public void sendMessage(String... messages) { + sendMessage(String.join("\n", messages)); + } + + @Override + public @NotNull String getName() { + return name; + } + + @Override + public boolean hasPermission(String permission) { + return permissionTest.test(permission); + } + + @Override + public boolean hasId(@NotNull UUID id) { + return id.equals(this.id); + } + + public @NotNull UUID getId() { + return id; + } + + public @NotNull Consumer getMessageConsumer() { + return messageConsumer; + } + + public @NotNull Predicate getPermissionTest() { + return permissionTest; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) + return false; + BasicCommandSender that = (BasicCommandSender) o; + return Objects.equals(handle, that.handle) && Objects.equals(name, that.name) && Objects.equals(id, that.id) + && Objects.equals(messageConsumer, that.messageConsumer) && Objects.equals(permissionTest, that.permissionTest); + } + + @Override + public int hashCode() { + return Objects.hash(handle, name, id, messageConsumer, permissionTest); + } + + @Override + public String toString() { + return "BasicCommandSender{" + + "handle=" + handle + + ", name='" + name + '\'' + + ", id=" + id + + ", messageConsumer=" + messageConsumer + + ", permissionTest=" + permissionTest + + '}'; + } + + public static Builder builder() { + return new Builder<>(); + } + + public static class Builder { + + private @Nullable S handle; + private @Nullable String name; + private @Nullable UUID id; + private @Nullable Consumer messageConsumer; + private @Nullable Predicate permissionTest; + + protected Builder() { + } + + public @Nullable S handle() { + return handle; + } + + public @NotNull Builder handle(@Nullable S handle) { + this.handle = handle; + return this; + } + + public @Nullable String name() { + return name; + } + + public @NotNull Builder name(@Nullable String name) { + this.name = name; + return this; + } + + public @Nullable UUID id() { + return id; + } + + public @NotNull Builder id(@Nullable UUID id) { + this.id = id; + return this; + } + + public @Nullable Consumer messageConsumer() { + return messageConsumer; + } + + public @NotNull Builder messageConsumer(@Nullable Consumer messageConsumer) { + this.messageConsumer = messageConsumer; + return this; + } + + public @Nullable Predicate permissionTest() { + return permissionTest; + } + + public @NotNull Builder permissionTest(@Nullable Predicate permissionTest) { + this.permissionTest = permissionTest; + return this; + } + + public @NotNull BasicCommandSender build() { + return new BasicCommandSender<>( + Objects.requireNonNull(handle, "the 'handler' can not be null"), + Objects.requireNonNull(name, "the 'name' can not be null"), + Objects.requireNonNull(id, "the 'id' can not be null"), + messageConsumer == null ? System.out::println : messageConsumer, + permissionTest == null ? permission -> true : permissionTest + ); + } + } +} diff --git a/commands/src/main/java/com/wizardlybump17/wlib/command/CommandSender.java b/commands/src/main/java/com/wizardlybump17/wlib/command/sender/CommandSender.java similarity index 54% rename from commands/src/main/java/com/wizardlybump17/wlib/command/CommandSender.java rename to commands/src/main/java/com/wizardlybump17/wlib/command/sender/CommandSender.java index c4b89aa3..0786ac74 100644 --- a/commands/src/main/java/com/wizardlybump17/wlib/command/CommandSender.java +++ b/commands/src/main/java/com/wizardlybump17/wlib/command/sender/CommandSender.java @@ -1,6 +1,8 @@ -package com.wizardlybump17.wlib.command; +package com.wizardlybump17.wlib.command.sender; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; /** * Represents a command sender, someone that can trigger commands. @@ -22,13 +24,5 @@ public interface CommandSender { boolean hasPermission(String permission); - /** - * Used to convert this CommandSender to a generic sender, a command sender that can be anything - * - * @return the generic sender - */ - @Nullable - default CommandSender toGeneric() { - return null; - } + boolean hasId(@NotNull UUID id); } diff --git a/commands/src/test/java/com/wizardlybump17/wlib/command/test/sender/BasicCommandSenderTests.java b/commands/src/test/java/com/wizardlybump17/wlib/command/test/sender/BasicCommandSenderTests.java new file mode 100644 index 00000000..6c66a360 --- /dev/null +++ b/commands/src/test/java/com/wizardlybump17/wlib/command/test/sender/BasicCommandSenderTests.java @@ -0,0 +1,64 @@ +package com.wizardlybump17.wlib.command.test.sender; + +import com.wizardlybump17.wlib.command.sender.BasicCommandSender; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +class BasicCommandSenderTests { + + @Test + void testPermissionsAllTrue() { + String name = "Test Sender"; + BasicCommandSender sender = BasicCommandSender.builder() + .handle(new Object()) + .name(name) + .id(UUID.nameUUIDFromBytes(name.getBytes())) + .permissionTest(permission -> true) + .build(); + Assertions.assertTrue(sender.hasPermission("test0.permission0")); + Assertions.assertTrue(sender.hasPermission("test0.permission1")); + Assertions.assertTrue(sender.hasPermission("test0.permission2")); + Assertions.assertTrue(sender.hasPermission("test1.permission0")); + Assertions.assertTrue(sender.hasPermission("test1.permission1")); + Assertions.assertTrue(sender.hasPermission("test1.permission2")); + } + + @Test + void testPermissionsAllFalse() { + String name = "Test Sender"; + BasicCommandSender sender = BasicCommandSender.builder() + .handle(new Object()) + .name(name) + .id(UUID.nameUUIDFromBytes(name.getBytes())) + .permissionTest(permission -> false) + .build(); + Assertions.assertFalse(sender.hasPermission("test0.permission0")); + Assertions.assertFalse(sender.hasPermission("test0.permission1")); + Assertions.assertFalse(sender.hasPermission("test0.permission2")); + Assertions.assertFalse(sender.hasPermission("test1.permission0")); + Assertions.assertFalse(sender.hasPermission("test1.permission1")); + Assertions.assertFalse(sender.hasPermission("test1.permission2")); + } + + @Test + void testSpecificPermissions() { + String name = "Test Sender"; + BasicCommandSender sender = BasicCommandSender.builder() + .handle(new Object()) + .name(name) + .id(UUID.nameUUIDFromBytes(name.getBytes())) + .permissionTest(permission -> permission.startsWith("test0.")) + .build(); + Assertions.assertTrue(sender.hasPermission("test0.permission0")); + Assertions.assertTrue(sender.hasPermission("test0.permission1")); + Assertions.assertTrue(sender.hasPermission("test0.permission2")); + Assertions.assertFalse(sender.hasPermission("test1.permission0")); + Assertions.assertFalse(sender.hasPermission("test1.permission1")); + Assertions.assertFalse(sender.hasPermission("test1.permission2")); + Assertions.assertFalse(sender.hasPermission("test2.permission0")); + Assertions.assertFalse(sender.hasPermission("test2.permission1")); + Assertions.assertFalse(sender.hasPermission("test2.permission2")); + } +} diff --git a/core/build.gradle b/core/build.gradle index 776fb140..b31666b8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -4,6 +4,9 @@ dependencies { 'org.jetbrains:annotations:23.1.0', 'org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT', ) + compileOnly("net.kyori:adventure-api:4.18.0") + compileOnly("net.kyori:adventure-text-minimessage:4.18.0") + compileOnly("net.kyori:adventure-platform-bukkit:4.3.4") annotationProcessor('org.projectlombok:lombok:1.18.24') implementation( diff --git a/core/src/main/java/com/wizardlybump17/wlib/WLib.java b/core/src/main/java/com/wizardlybump17/wlib/WLib.java index 5360dca2..bf90d6db 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/WLib.java +++ b/core/src/main/java/com/wizardlybump17/wlib/WLib.java @@ -3,6 +3,7 @@ import com.wizardlybump17.wlib.adapter.EnchantmentAdapter; import com.wizardlybump17.wlib.adapter.ItemAdapter; import com.wizardlybump17.wlib.adapter.PotionEffectTypeAdapter; +import com.wizardlybump17.wlib.adapter.command.CommandMapAdapter; import com.wizardlybump17.wlib.adapter.v1_19_R2.player.PlayerAdapter; import com.wizardlybump17.wlib.command.args.ArgsReaderRegistry; import com.wizardlybump17.wlib.command.reader.*; @@ -28,15 +29,18 @@ import com.wizardlybump17.wlib.util.bukkit.particle.*; import lombok.Getter; import lombok.NonNull; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bukkit.Bukkit; import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.event.HandlerList; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; @Getter public class WLib extends JavaPlugin { private final SaveControllersTask saveControllersTask = new SaveControllersTask(getLogger()); + private BukkitAudiences audiences; @Override public void onLoad() { @@ -63,6 +67,8 @@ protected void initConfigs() { @Override public void onEnable() { + audiences = BukkitAudiences.create(this); + Bukkit.getPluginManager().registerEvents(new EntityListener(), this); Bukkit.getPluginManager().registerEvents(new PlayerListener(this), this); @@ -75,6 +81,11 @@ public void onEnable() { public void onDisable() { HandlerList.unregisterAll(this); saveControllersTask.cancel(); + + if (audiences != null) { + audiences.close(); + audiences = null; + } } private void initCommandSystem() { @@ -121,60 +132,70 @@ private void setupAdapters() { PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_16_R3.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_16_R3.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_16_R3.command.CommandMapAdapter()); } case V1_17_1 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_17_R1.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_17_R1.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_17_R1.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_17_R1.command.CommandMapAdapter()); } case V1_18 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R1.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R1.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R1.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R1.command.CommandMapAdapter()); } case V1_18_2 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R2.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R2.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R2.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_18_R2.command.CommandMapAdapter()); } case V1_19 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R1.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R1.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R1.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R1.command.CommandMapAdapter()); } case V1_19_3 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R2.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R2.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R2.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R2.command.CommandMapAdapter()); } case V1_19_4 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R3.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R3.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R3.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_19_R3.command.CommandMapAdapter()); } case V1_20_1 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R1.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R1.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R1.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R1.command.CommandMapAdapter()); } case V1_20_2 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R2.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R2.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R2.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R2.command.CommandMapAdapter()); } case V1_20_4 -> { ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R3.ItemAdapter()); PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R3.player.PlayerAdapter()); PotionEffectTypeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R3.PotionEffectTypeAdapter()); EnchantmentAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R3.EnchantmentAdapter()); + CommandMapAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_20_R3.command.CommandMapAdapter()); } } @@ -194,4 +215,8 @@ public static WLib getInstance() { public static @NonNull String getServerVersion() { return Bukkit.getServer().getClass().getName().split("\\.")[3]; } + + public @NotNull BukkitAudiences getAudiences() { + return audiences; + } } diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/BukkitCommandExecutor.java b/core/src/main/java/com/wizardlybump17/wlib/command/BukkitCommandExecutor.java index c5577b03..c878081f 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/BukkitCommandExecutor.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/BukkitCommandExecutor.java @@ -1,54 +1,41 @@ package com.wizardlybump17.wlib.command; -import com.wizardlybump17.wlib.command.sender.ConsoleSender; -import com.wizardlybump17.wlib.command.sender.GenericSender; -import com.wizardlybump17.wlib.command.sender.PlayerSender; +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.sender.BukkitCommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.*; -import org.bukkit.entity.Player; +import org.bukkit.command.TabExecutor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.logging.Level; @RequiredArgsConstructor public class BukkitCommandExecutor implements TabExecutor, com.wizardlybump17.wlib.command.holder.CommandExecutor { private final CommandManager manager; - @SneakyThrows @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { - execute(getSender(sender), command.getName(), args); + public boolean onCommand(@NotNull org.bukkit.command.CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + try { + execute(new BukkitCommandSender(sender), command.getName(), args); + } catch (CommandException e) { + manager.getHolder().getLogger().log(Level.SEVERE, "Error while executing a command", e); + } return false; } @Override - public void execute(com.wizardlybump17.wlib.command.CommandSender sender, String commandName, String[] args) { + public void execute(CommandSender sender, String commandName, String[] args) throws CommandException { String commandExecution = commandName + " " + String.join(" ", args); manager.execute(sender, commandExecution); } @Nullable @Override - public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { -// String fullCommand = command.getName() + " " + String.join(" ", args); -// List suggestions = manager.autoComplete(getSender(sender), fullCommand); -// ArrayList strings = StringUtil.copyPartialMatches(args[args.length - 1], suggestions, new ArrayList<>(suggestions.size())); -// return strings; + public List onTabComplete(@NotNull org.bukkit.command.CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { return null; } - - private com.wizardlybump17.wlib.command.CommandSender getSender(CommandSender original) { - if (original instanceof Player player) - return new PlayerSender(player); - if (original instanceof ConsoleCommandSender consoleSender) - return new ConsoleSender(consoleSender); - if (original instanceof BlockCommandSender blockSender) - return new com.wizardlybump17.wlib.command.sender.BlockCommandSender(blockSender); - return new GenericSender(original); - } } diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/completer/EntityTypeArgumentCompleter.java b/core/src/main/java/com/wizardlybump17/wlib/command/completer/EntityTypeArgumentCompleter.java index de7bf8f4..2068365d 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/completer/EntityTypeArgumentCompleter.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/completer/EntityTypeArgumentCompleter.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.completer; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.entity.EntityType; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/completer/MaterialArgumentCompleter.java b/core/src/main/java/com/wizardlybump17/wlib/command/completer/MaterialArgumentCompleter.java index 6ded4874..8c72508f 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/completer/MaterialArgumentCompleter.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/completer/MaterialArgumentCompleter.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.completer; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.Material; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/completer/PlayerArgumentCompleter.java b/core/src/main/java/com/wizardlybump17/wlib/command/completer/PlayerArgumentCompleter.java index 2d963104..29145e42 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/completer/PlayerArgumentCompleter.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/completer/PlayerArgumentCompleter.java @@ -1,6 +1,6 @@ package com.wizardlybump17.wlib.command.completer; -import com.wizardlybump17.wlib.command.CommandSender; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/reader/BlockDataArgsReader.java b/core/src/main/java/com/wizardlybump17/wlib/command/reader/BlockDataArgsReader.java index dca102c3..8b9ca548 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/reader/BlockDataArgsReader.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/reader/BlockDataArgsReader.java @@ -1,8 +1,8 @@ package com.wizardlybump17.wlib.command.reader; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReader; import com.wizardlybump17.wlib.command.args.reader.ArgsReaderException; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.Material; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/reader/EntityTypeArgsReader.java b/core/src/main/java/com/wizardlybump17/wlib/command/reader/EntityTypeArgsReader.java index 4ca9a7ce..c6986ffb 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/reader/EntityTypeArgsReader.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/reader/EntityTypeArgsReader.java @@ -1,7 +1,7 @@ package com.wizardlybump17.wlib.command.reader; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReader; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.entity.EntityType; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/reader/MapJsonArgsReader.java b/core/src/main/java/com/wizardlybump17/wlib/command/reader/MapJsonArgsReader.java index a456c1c8..d7c82251 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/reader/MapJsonArgsReader.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/reader/MapJsonArgsReader.java @@ -2,9 +2,9 @@ import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReader; import com.wizardlybump17.wlib.command.args.reader.ArgsReaderException; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import java.util.List; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/reader/MaterialReader.java b/core/src/main/java/com/wizardlybump17/wlib/command/reader/MaterialReader.java index 8251dd9c..2daf7f90 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/reader/MaterialReader.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/reader/MaterialReader.java @@ -1,7 +1,7 @@ package com.wizardlybump17.wlib.command.reader; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReader; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.Material; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/reader/OfflinePlayerReader.java b/core/src/main/java/com/wizardlybump17/wlib/command/reader/OfflinePlayerReader.java index 5da69881..46c29ea4 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/reader/OfflinePlayerReader.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/reader/OfflinePlayerReader.java @@ -1,7 +1,7 @@ package com.wizardlybump17.wlib.command.reader; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReader; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/reader/PlayerReader.java b/core/src/main/java/com/wizardlybump17/wlib/command/reader/PlayerReader.java index ddb38aa7..1521ff37 100644 --- a/core/src/main/java/com/wizardlybump17/wlib/command/reader/PlayerReader.java +++ b/core/src/main/java/com/wizardlybump17/wlib/command/reader/PlayerReader.java @@ -1,7 +1,7 @@ package com.wizardlybump17.wlib.command.reader; -import com.wizardlybump17.wlib.command.CommandSender; import com.wizardlybump17.wlib.command.args.reader.ArgsReader; +import com.wizardlybump17.wlib.command.sender.CommandSender; import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredBukkitCommand.java b/core/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredBukkitCommand.java new file mode 100644 index 00000000..46ea8992 --- /dev/null +++ b/core/src/main/java/com/wizardlybump17/wlib/command/registered/RegisteredBukkitCommand.java @@ -0,0 +1,59 @@ +package com.wizardlybump17.wlib.command.registered; + +import com.wizardlybump17.wlib.adapter.command.CommandMapAdapter; +import com.wizardlybump17.wlib.command.CommandManager; +import com.wizardlybump17.wlib.command.args.ArgsNode; +import com.wizardlybump17.wlib.command.data.CommandData; +import com.wizardlybump17.wlib.command.exception.CommandException; +import com.wizardlybump17.wlib.command.executor.CommandExecutor; +import com.wizardlybump17.wlib.command.sender.BukkitCommandSender; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class RegisteredBukkitCommand extends RegisteredCommand { + + private final @NotNull String fallback; + + public RegisteredBukkitCommand(@NotNull CommandData command, @NotNull List nodes, @NotNull CommandExecutor executor, @NotNull String fallback) { + super(command, nodes, executor); + this.fallback = fallback; + } + + public @NotNull String getFallback() { + return fallback; + } + + @Override + public void onRegister(@NotNull CommandManager manager) { + CommandMap commandMap = CommandMapAdapter.getInstance().getCommandMap(); + String name = getCommand().getName(); + Logger logger = manager.getHolder().getLogger(); + + commandMap.register(name, fallback, new Command(name) { + @Override + public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { + try { + manager.execute(new BukkitCommandSender(sender), name + " " + String.join(" ", args)); + } catch (CommandException e) { + logger.log(Level.SEVERE, "Error while executing a command.", e); + } + return false; + } + }); + } + + @Override + public void onUnregister(@NotNull CommandManager manager) { + CommandMapAdapter adapter = CommandMapAdapter.getInstance(); + + String name = getCommand().getName(); + adapter.unregisterCommand(name); + adapter.unregisterCommand(fallback + ":" + name); + } +} diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/sender/AbstractSender.java b/core/src/main/java/com/wizardlybump17/wlib/command/sender/AbstractSender.java deleted file mode 100644 index 98af7103..00000000 --- a/core/src/main/java/com/wizardlybump17/wlib/command/sender/AbstractSender.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.wizardlybump17.wlib.command.sender; - -import com.wizardlybump17.wlib.command.CommandSender; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public abstract class AbstractSender implements CommandSender { - - private final S handle; - - @Override - public void sendMessage(String message) { - handle.sendMessage(message); - } - - @Override - public void sendMessage(String... message) { - handle.sendMessage(String.join("\n", message)); - } - - @Override - public String getName() { - return handle.getName(); - } - - @Override - public boolean hasPermission(String permission) { - return handle.hasPermission(permission); - } - - @Override - @NonNull - public GenericSender toGeneric() { - return new GenericSender(handle); - } -} diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/sender/BlockCommandSender.java b/core/src/main/java/com/wizardlybump17/wlib/command/sender/BlockCommandSender.java deleted file mode 100644 index 2f3b8455..00000000 --- a/core/src/main/java/com/wizardlybump17/wlib/command/sender/BlockCommandSender.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.wizardlybump17.wlib.command.sender; - -public class BlockCommandSender extends AbstractSender { - - public BlockCommandSender(org.bukkit.command.BlockCommandSender handle) { - super(handle); - } -} diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/sender/BukkitCommandSender.java b/core/src/main/java/com/wizardlybump17/wlib/command/sender/BukkitCommandSender.java new file mode 100644 index 00000000..d13d6355 --- /dev/null +++ b/core/src/main/java/com/wizardlybump17/wlib/command/sender/BukkitCommandSender.java @@ -0,0 +1,90 @@ +package com.wizardlybump17.wlib.command.sender; + +import com.wizardlybump17.wlib.WLib; +import com.wizardlybump17.wlib.util.bukkit.MiniMessageUtil; +import net.kyori.adventure.chat.ChatType; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.UUID; + +public class BukkitCommandSender implements CommandSender { + + private final @NotNull org.bukkit.command.CommandSender handle; + + public BukkitCommandSender(@NotNull org.bukkit.command.CommandSender handle) { + this.handle = handle; + } + + @Override + public org.bukkit.command.CommandSender getHandle() { + return handle; + } + + @Override + public void sendMessage(String message) { + handle.sendMessage(message); + } + + @Override + public void sendMessage(String... message) { + handle.sendMessage(String.join("\n", message)); + } + + public void sendMiniMessage(@NotNull String message, @NotNull Map placeholders) { + WLib.getInstance().getAudiences().sender(handle).sendMessage(MiniMessageUtil.getMessage(message, placeholders)); + } + + public void sendMiniMessage(@NotNull String message) { + sendMiniMessage(message, Map.of()); + } + + public void sendMessage(@NotNull Component message) { + WLib.getInstance().getAudiences().sender(handle).sendMessage(message); + } + + public void sendMessage(@NotNull Component message, @NotNull ChatType.Bound type) { + WLib.getInstance().getAudiences().sender(handle).sendMessage(message, type); + } + + public void sendMessage(@NotNull ComponentLike message) { + WLib.getInstance().getAudiences().sender(handle).sendMessage(message); + } + + public void sendMessage(@NotNull ComponentLike message, @NotNull ChatType.Bound type) { + WLib.getInstance().getAudiences().sender(handle).sendMessage(message, type); + } + + @Override + public String getName() { + return handle.getName(); + } + + @Override + public boolean hasPermission(String permission) { + return handle.hasPermission(permission); + } + + public @NotNull BlockCommandSender asBlockCommand() { + return (BlockCommandSender) handle; + } + + public @NotNull ConsoleCommandSender asConsole() { + return (ConsoleCommandSender) handle; + } + + public @NotNull Player asPlayer() { + return (Player) handle; + } + + @Override + public boolean hasId(@NotNull UUID id) { + return handle instanceof Entity entity && entity.getUniqueId().equals(id); + } +} diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/sender/ConsoleSender.java b/core/src/main/java/com/wizardlybump17/wlib/command/sender/ConsoleSender.java deleted file mode 100644 index 46e55e01..00000000 --- a/core/src/main/java/com/wizardlybump17/wlib/command/sender/ConsoleSender.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.wizardlybump17.wlib.command.sender; - -import org.bukkit.command.ConsoleCommandSender; - -public class ConsoleSender extends AbstractSender { - - public ConsoleSender(ConsoleCommandSender handle) { - super(handle); - } -} diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/sender/GenericSender.java b/core/src/main/java/com/wizardlybump17/wlib/command/sender/GenericSender.java deleted file mode 100644 index d223526d..00000000 --- a/core/src/main/java/com/wizardlybump17/wlib/command/sender/GenericSender.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.wizardlybump17.wlib.command.sender; - -import lombok.NonNull; -import org.bukkit.command.CommandSender; - -public class GenericSender extends AbstractSender { - - public GenericSender(CommandSender handle) { - super(handle); - } - - @Override - @NonNull - public GenericSender toGeneric() { - return this; - } - - public static boolean isGeneric() { - return true; - } -} diff --git a/core/src/main/java/com/wizardlybump17/wlib/command/sender/PlayerSender.java b/core/src/main/java/com/wizardlybump17/wlib/command/sender/PlayerSender.java deleted file mode 100644 index ac2f08eb..00000000 --- a/core/src/main/java/com/wizardlybump17/wlib/command/sender/PlayerSender.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.wizardlybump17.wlib.command.sender; - -import org.bukkit.entity.Player; - -public class PlayerSender extends AbstractSender { - - public PlayerSender(Player handle) { - super(handle); - } -} diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index dee76513..35676d43 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -3,4 +3,8 @@ main: com.wizardlybump17.wlib.WLib version: '${version}' author: WizardlyBump17 api-version: '1.13' -load: STARTUP \ No newline at end of file +load: STARTUP +libraries: + - net.kyori:adventure-api:4.18.0 + - net.kyori:adventure-text-minimessage:4.18.0 + - net.kyori:adventure-platform-bukkit:4.3.4 diff --git a/versions/adapter/src/main/java/com/wizardlybump17/wlib/adapter/command/CommandMapAdapter.java b/versions/adapter/src/main/java/com/wizardlybump17/wlib/adapter/command/CommandMapAdapter.java new file mode 100644 index 00000000..14a001ae --- /dev/null +++ b/versions/adapter/src/main/java/com/wizardlybump17/wlib/adapter/command/CommandMapAdapter.java @@ -0,0 +1,28 @@ +package com.wizardlybump17.wlib.adapter.command; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public abstract class CommandMapAdapter { + + private static CommandMapAdapter instance; + + public abstract @NotNull CommandMap getCommandMap(); + + public abstract void unregisterCommand(@NotNull String command); + + public abstract @NotNull Map getCommands(); + + public static CommandMapAdapter getInstance() { + return instance; + } + + public static void setInstance(@NotNull CommandMapAdapter instance) { + if (CommandMapAdapter.instance != null) + throw new IllegalStateException("The CommandAdapter instance is already set."); + CommandMapAdapter.instance = instance; + } +} diff --git a/versions/v1_16_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_16_R3/command/CommandMapAdapter.java b/versions/v1_16_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_16_R3/command/CommandMapAdapter.java new file mode 100644 index 00000000..f2461fd8 --- /dev/null +++ b/versions/v1_16_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_16_R3/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_16_R3.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_17_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_17_R1/command/CommandMapAdapter.java b/versions/v1_17_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_17_R1/command/CommandMapAdapter.java new file mode 100644 index 00000000..3e6d948d --- /dev/null +++ b/versions/v1_17_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_17_R1/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_17_R1.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_18_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_18_R1/command/CommandMapAdapter.java b/versions/v1_18_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_18_R1/command/CommandMapAdapter.java new file mode 100644 index 00000000..aa747170 --- /dev/null +++ b/versions/v1_18_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_18_R1/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_18_R1.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_18_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_18_R2/command/CommandMapAdapter.java b/versions/v1_18_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_18_R2/command/CommandMapAdapter.java new file mode 100644 index 00000000..cdb45016 --- /dev/null +++ b/versions/v1_18_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_18_R2/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_18_R2.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_19_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R1/command/CommandMapAdapter.java b/versions/v1_19_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R1/command/CommandMapAdapter.java new file mode 100644 index 00000000..a5ce6522 --- /dev/null +++ b/versions/v1_19_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R1/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_19_R1.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_19_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R2/command/CommandMapAdapter.java b/versions/v1_19_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R2/command/CommandMapAdapter.java new file mode 100644 index 00000000..4b7b0639 --- /dev/null +++ b/versions/v1_19_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R2/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_19_R2.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_19_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R3/command/CommandMapAdapter.java b/versions/v1_19_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R3/command/CommandMapAdapter.java new file mode 100644 index 00000000..e0b6df28 --- /dev/null +++ b/versions/v1_19_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_19_R3/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_19_R3.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_20_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R1/command/CommandMapAdapter.java b/versions/v1_20_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R1/command/CommandMapAdapter.java new file mode 100644 index 00000000..98a07dd8 --- /dev/null +++ b/versions/v1_20_R1/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R1/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_20_R1.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_20_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R2/command/CommandMapAdapter.java b/versions/v1_20_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R2/command/CommandMapAdapter.java new file mode 100644 index 00000000..b14f309f --- /dev/null +++ b/versions/v1_20_R2/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R2/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_20_R2.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +} diff --git a/versions/v1_20_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R3/command/CommandMapAdapter.java b/versions/v1_20_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R3/command/CommandMapAdapter.java new file mode 100644 index 00000000..2c867d02 --- /dev/null +++ b/versions/v1_20_R3/src/main/java/com/wizardlybump17/wlib/adapter/v1_20_R3/command/CommandMapAdapter.java @@ -0,0 +1,37 @@ +package com.wizardlybump17.wlib.adapter.v1_20_R3.command; + +import com.wizardlybump17.wlib.util.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Map; + +public class CommandMapAdapter extends com.wizardlybump17.wlib.adapter.command.CommandMapAdapter { + + public static final @NotNull Field COMMAND_MAP = ReflectionUtil.getField("commandMap", Bukkit.getServer().getClass()); + public static final @NotNull Field COMMANDS = ReflectionUtil.getField("knownCommands", SimpleCommandMap.class); + + @Override + public @NotNull CommandMap getCommandMap() { + return ReflectionUtil.getFieldValue(COMMAND_MAP, Bukkit.getServer()); + } + + @Override + public void unregisterCommand(@NotNull String command) { + Map commands = getCommands(); + CommandMap commandMap = getCommandMap(); + + Command removed = commands.remove(command); + if (removed != null) + removed.unregister(commandMap); + } + + @Override + public @NotNull Map getCommands() { + return ReflectionUtil.getFieldValue(COMMANDS, getCommandMap()); + } +}