commands work but i think ill refactor
This commit is contained in:
parent
5b5cb04f8b
commit
36a13443db
54 changed files with 726 additions and 812 deletions
|
|
@ -19,9 +19,6 @@ subprojects {
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
|
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
|
||||||
name = "spigotmc-repo"
|
name = "spigotmc-repo"
|
||||||
}
|
}
|
||||||
maven("https://libraries.minecraft.net") {
|
|
||||||
name = "Minecraft Libraries"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,10 @@ dependencies {
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
|
||||||
api("me.lucko:commodore:2.2")
|
|
||||||
api("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
api("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
||||||
api("net.kyori:adventure-platform-bukkit:4.4.1")
|
api("net.kyori:adventure-platform-bukkit:4.4.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.findByName("shadowJar")?.let {
|
|
||||||
dependencies {
|
|
||||||
"exclude"("dependency"("com.mojang.brigadier")!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create<MavenPublication>("CoreBukkitApi") {
|
create<MavenPublication>("CoreBukkitApi") {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command;
|
package de.kentoj.scrow.bukkit.services.command;
|
||||||
|
|
||||||
public interface CommandReader {
|
public interface ArgumentReader {
|
||||||
|
|
||||||
boolean isEOF();
|
boolean isEOF();
|
||||||
|
|
||||||
String readWord();
|
String readWord();
|
||||||
|
|
||||||
String readQuotedString();
|
String readQuotedWord();
|
||||||
|
|
||||||
int getCursor();
|
int getCursor();
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
// TODO convert to interface
|
|
||||||
@Value
|
|
||||||
public class CommandArgument<T> {
|
|
||||||
int index;
|
|
||||||
String name;
|
|
||||||
ArgumentType<T> type;
|
|
||||||
Function<CommandContext, T> defaultValue;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command;
|
package de.kentoj.scrow.bukkit.services.command;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
|
||||||
public interface CommandExecutor {
|
public interface CommandExecutor {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command;
|
package de.kentoj.scrow.bukkit.services.command;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
public interface CommandManager {
|
public interface CommandManager {
|
||||||
|
|
||||||
void register(CommandNode rootCommandNode, Plugin plugin);
|
void register(RootLiteral rootLiteral, Plugin plugin);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,20 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface CommandArgument<T> {
|
public interface CommandArgument<T> {
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
ArgumentType<T> getType();
|
ArgumentType<T> getType();
|
||||||
|
|
||||||
@Nullable T getDefaultValue(CommandContext ctx);
|
@Nullable T getDefaultValue(CommandContext ctx);
|
||||||
|
|
||||||
|
void setSuggestionProvider(@Nullable SuggestionProvider suggestionProvider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the explicitly set SuggestionProvider or the suggestions for the type if unset/null
|
||||||
|
*/
|
||||||
|
SuggestionProvider getSuggestionProvider();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.context;
|
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public interface CommandContext {
|
public interface CommandContext {
|
||||||
|
|
||||||
|
|
@ -16,12 +15,11 @@ public interface CommandContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Object that is parsed from the raw argument
|
* @return Object that is parsed from the raw argument
|
||||||
* @throws CommandSyntaxException if no value given and no default value supplied
|
* @throws CommandInvocationException if no value given and no default value supplied
|
||||||
*/
|
*/
|
||||||
<T> T getArg(String key);
|
<T> T getArg(String name);
|
||||||
|
|
||||||
/**
|
default <T> T getArg(CommandArgument<T> arg) {
|
||||||
* @return string argument used at invocation
|
return getArg(arg.getName());
|
||||||
*/
|
}
|
||||||
@Nullable String getRawArgument(String key);
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.Literal;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface CommandFactory {
|
||||||
|
|
||||||
|
Literal literal(String name);
|
||||||
|
|
||||||
|
RootLiteral root(String name);
|
||||||
|
|
||||||
|
<T> CommandArgument<T> argument(String name, ArgumentType<T> type, Function<CommandContext, T> defaultValueFun);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.Literal;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class Commands {
|
||||||
|
|
||||||
|
private static CommandFactory factory;
|
||||||
|
|
||||||
|
public static Literal literal(String name) {
|
||||||
|
return factory.literal(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RootLiteral root(String name) {
|
||||||
|
return factory.root(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> CommandArgument<T> argument0(String name, ArgumentType<T> type, Function<CommandContext, T> defaultValueFun) {
|
||||||
|
return factory.argument(name, type, defaultValueFun);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> CommandArgument<T> argument1(String name, ArgumentType<T> type, T defaultValue) {
|
||||||
|
return factory.argument(name, type, __ -> defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> CommandArgument<T> argument0(String name, ArgumentType<T> type) {
|
||||||
|
return factory.argument(name, type, __ -> null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public static void setFactory(CommandFactory factory) {
|
||||||
|
Commands.factory = factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
package de.kentoj.scrow.bukkit.services.command.cmds2;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface SuggestionProvider {
|
public interface SuggestionProvider {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.cmds2.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public non-sealed interface ArgumentCommandNode extends CommandNode {
|
|
||||||
|
|
||||||
<T> ArgumentType<T> getArgument(String name);
|
|
||||||
|
|
||||||
void addArgument(String name, ArgumentType<?> arg);
|
|
||||||
<T> void addArgument(String name, ArgumentType<T> arg, Function<CommandContext, T> getDefault);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.cmds2.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.SuggestionProvider;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public sealed interface CommandNode permits LiteralCommandNode, ArgumentCommandNode, RootCommandNode {
|
|
||||||
|
|
||||||
void setName(String name);
|
|
||||||
String getName();
|
|
||||||
|
|
||||||
void addSubNode(CommandNode node);
|
|
||||||
@Nullable CommandNode getSubNode(String rawArg);
|
|
||||||
boolean hasNextNode();
|
|
||||||
|
|
||||||
void setExecutor(@Nullable CommandExecutor executor);
|
|
||||||
@Nullable CommandExecutor getExecutor();
|
|
||||||
|
|
||||||
void setSuggestionProvider(SuggestionProvider suggestionProvider);
|
|
||||||
SuggestionProvider getSuggestionProvider();
|
|
||||||
|
|
||||||
void setDescription(@Nullable String description);
|
|
||||||
@Nullable String getDescription();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package de.kentoj.scrow.bukkit.services.command.cmds2.node;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandArgument;
|
||||||
|
import org.bukkit.permissions.Permission;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Literal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String with no spaces!
|
||||||
|
*/
|
||||||
|
void setName(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String with no spaces!
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
void addLiteral(Literal node);
|
||||||
|
|
||||||
|
@Nullable Literal getLiteral(String rawArg);
|
||||||
|
|
||||||
|
boolean hasLiteral();
|
||||||
|
|
||||||
|
void setExecutor(@Nullable CommandExecutor executor);
|
||||||
|
|
||||||
|
@Nullable CommandExecutor getExecutor();
|
||||||
|
|
||||||
|
void setDescription(@Nullable String description);
|
||||||
|
|
||||||
|
@Nullable String getDescription();
|
||||||
|
|
||||||
|
Permission getRequiredPermission();
|
||||||
|
|
||||||
|
void setRequiredPermission(Permission permission);
|
||||||
|
|
||||||
|
<T> void addArgument(CommandArgument<T> argument);
|
||||||
|
|
||||||
|
List<CommandArgument<?>> getArguments();
|
||||||
|
}
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.cmds2.node;
|
|
||||||
|
|
||||||
import org.bukkit.permissions.Permission;
|
|
||||||
|
|
||||||
public non-sealed interface LiteralCommandNode extends CommandNode {
|
|
||||||
|
|
||||||
Permission getRequiredPermission();
|
|
||||||
|
|
||||||
void setRequiredPermission(Permission permission);
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@ package de.kentoj.scrow.bukkit.services.command.cmds2.node;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public non-sealed interface RootCommandNode extends CommandNode, LiteralCommandNode {
|
public interface RootLiteral extends Literal {
|
||||||
|
|
||||||
Set<String> getAliases();
|
Set<String> getAliases();
|
||||||
|
|
||||||
|
|
@ -4,19 +4,19 @@ package de.kentoj.scrow.bukkit.services.command.exception;
|
||||||
* When a command has a syntax issue.
|
* When a command has a syntax issue.
|
||||||
* {@code CommandSyntaxException::getMessage} should return a user-friendly message explaining the issue.
|
* {@code CommandSyntaxException::getMessage} should return a user-friendly message explaining the issue.
|
||||||
*/
|
*/
|
||||||
public class CommandSyntaxException extends RuntimeException {
|
public class CommandInvocationException extends RuntimeException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param message user-friendly message
|
* @param message user-friendly message
|
||||||
*/
|
*/
|
||||||
public CommandSyntaxException(String message) {
|
public CommandInvocationException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param message user-friendly message
|
* @param message user-friendly message
|
||||||
*/
|
*/
|
||||||
public CommandSyntaxException(String message, Throwable throwable) {
|
public CommandInvocationException(String message, Throwable throwable) {
|
||||||
super(message + ": " + throwable.getMessage());
|
super(message + ": " + throwable.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
|
||||||
import org.bukkit.permissions.Permission;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
// TODO javadoc
|
|
||||||
public interface CommandNode {
|
|
||||||
|
|
||||||
void setPermission(@Nullable Permission permission);
|
|
||||||
|
|
||||||
default void setPermission(String permission) {
|
|
||||||
setPermission(new Permission(permission));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDescription(String description);
|
|
||||||
|
|
||||||
void setAliases(Set<String> aliases);
|
|
||||||
|
|
||||||
void addAlias(String... aliases);
|
|
||||||
|
|
||||||
void setExecutor(@Nullable CommandExecutor executor);
|
|
||||||
|
|
||||||
@Nullable Permission getPermission();
|
|
||||||
|
|
||||||
String getName();
|
|
||||||
|
|
||||||
Set<String> getAliases();
|
|
||||||
|
|
||||||
String getDescription();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that should be called when invoking this command.
|
|
||||||
* The executor shall only be called when this node is the last CommandNode in the invocation.
|
|
||||||
* <pre>
|
|
||||||
* - RootCommand(CommandNode)
|
|
||||||
* - has executor
|
|
||||||
* - has sub-command(CommandNode)
|
|
||||||
* - has executor
|
|
||||||
* </pre>
|
|
||||||
* In this case, the sub-command is optional. If the sub-command is used, the sub-command's executor will be used.
|
|
||||||
* Else the RootCommand's executor will be used.
|
|
||||||
*/
|
|
||||||
@Nullable CommandExecutor getExecutor();
|
|
||||||
|
|
||||||
default boolean hasExecutor() {
|
|
||||||
return getExecutor() != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.node;
|
|
||||||
|
|
||||||
public interface CommandNodeFactory {
|
|
||||||
|
|
||||||
CommandNodeWithSubCommand createNodeWithSubCommands(String name);
|
|
||||||
|
|
||||||
CommandNodeWithArguments createNodeWithArguments(String name);
|
|
||||||
|
|
||||||
CommandNode createRootNode(String name);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.node;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class CommandNodeRepository {
|
|
||||||
|
|
||||||
private static CommandNodeFactory commandNodeFactory;
|
|
||||||
|
|
||||||
public static CommandNodeWithArguments withArguments(String name) {
|
|
||||||
return commandNodeFactory.createNodeWithArguments(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CommandNodeWithSubCommand withSubCommands(String name) {
|
|
||||||
return commandNodeFactory.createNodeWithSubCommands(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiStatus.Internal
|
|
||||||
public static void setCommandNodeFactory(CommandNodeFactory commandNodeFactory) {
|
|
||||||
CommandNodeRepository.commandNodeFactory = commandNodeFactory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandArgument;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A CommandNode which can have arguments
|
|
||||||
*/
|
|
||||||
public interface CommandNodeWithArguments extends CommandNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an argument to the node.
|
|
||||||
* @param defaultValue Function returning a defaultValue if no value is given at invocation. \
|
|
||||||
* May be null if the argument should be required and not optional.
|
|
||||||
* @throws IllegalStateException if the previous argument is optional(defaultValue is set) and this is not.
|
|
||||||
*/
|
|
||||||
<T> void addArg(String name, ArgumentType<T> type, @Nullable Function<CommandContext, T> defaultValue);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a required argument to the node
|
|
||||||
* @throws IllegalStateException if the previous argument is optional(defaultValue is set) and this is not.
|
|
||||||
*/
|
|
||||||
default <T> void addArg(String name, ArgumentType<T> type) {
|
|
||||||
addArg(name, type, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable CommandArgument<?> getArg(int index);
|
|
||||||
|
|
||||||
@Nullable CommandArgument<?> getArg(String name);
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.node;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A CommandNode which can have sub-commands
|
|
||||||
*/
|
|
||||||
public interface CommandNodeWithSubCommand extends CommandNode {
|
|
||||||
|
|
||||||
List<CommandNode> getSubCommands();
|
|
||||||
|
|
||||||
void addSubCommand(CommandNode subCommand);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return SubCommand node where a name or alias matches label
|
|
||||||
*/
|
|
||||||
@Nullable CommandNode getSubCommand(String label);
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.type;
|
package de.kentoj.scrow.bukkit.services.command.type;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandReader;
|
import de.kentoj.scrow.bukkit.services.command.ArgumentReader;
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface ArgumentType<T> {
|
public interface ArgumentType<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws CommandSyntaxException if the given value may not be used
|
* @throws CommandInvocationException if the given value may not be used
|
||||||
*/
|
*/
|
||||||
void checkValue(CommandContext ctx, T value, String rawValue) throws CommandSyntaxException;
|
void checkValue(CommandContext ctx, T value) throws CommandInvocationException;
|
||||||
|
|
||||||
Set<String> getDefaultSuggestions(CommandContext ctx);
|
Set<String> getDefaultSuggestions(CommandContext ctx);
|
||||||
|
|
||||||
T parseInput(CommandReader reader);
|
T parseInput(ArgumentReader reader);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.services.command.type;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandReader;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
// TODO add livingEntity
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class EntityArgumentType {
|
|
||||||
|
|
||||||
private static final ArgumentType<Player> player = new ArgumentType<>() {
|
|
||||||
@Override
|
|
||||||
public void checkValue(CommandContext ctx, Player value, String rawValue) throws CommandSyntaxException {
|
|
||||||
if (value == null)
|
|
||||||
throw new CommandSyntaxException("Player is not online -- " + rawValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getDefaultSuggestions(CommandContext ctx) {
|
|
||||||
return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Player parseInput(CommandReader reader) {
|
|
||||||
final var word = reader.readWord();
|
|
||||||
if (word.length() == 36) {
|
|
||||||
var uuid = UUID.fromString(word);
|
|
||||||
return Bukkit.getPlayer(uuid);
|
|
||||||
} else {
|
|
||||||
return Bukkit.getPlayerExact(word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static ArgumentType<Player> player() {
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package de.kentoj.scrow.bukkit.services.command.type;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.ArgumentReader;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
// TODO add livingEntity
|
||||||
|
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class NumberArgumentType {
|
||||||
|
|
||||||
|
public static ArgumentType<Integer> integer(int min, int max) {
|
||||||
|
Preconditions.checkArgument(min < max, "min is greater than max");
|
||||||
|
|
||||||
|
return new ArgumentType<>() {
|
||||||
|
@Override
|
||||||
|
public void checkValue(CommandContext ctx, Integer value) throws CommandInvocationException {
|
||||||
|
if (value < min) throw new CommandInvocationException("Value too small -- " + value);
|
||||||
|
if (value > max) throw new CommandInvocationException("Value too large -- " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDefaultSuggestions(CommandContext ctx) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer parseInput(ArgumentReader reader) {
|
||||||
|
final var str = reader.readWord();
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(str);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
throw new CommandInvocationException("Invalid number -- " + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package de.kentoj.scrow.bukkit.services.command.type;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.ArgumentReader;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
// TODO add livingEntity
|
||||||
|
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class PlayerArgumentType {
|
||||||
|
|
||||||
|
private static final ArgumentType<Player> player = new ArgumentType<>() {
|
||||||
|
@Override
|
||||||
|
public void checkValue(CommandContext ctx, Player value) throws CommandInvocationException {
|
||||||
|
if (value == null)
|
||||||
|
throw new CommandInvocationException("Player is not online");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDefaultSuggestions(CommandContext ctx) {
|
||||||
|
return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Player parseInput(ArgumentReader reader) {
|
||||||
|
final var word = reader.readWord();
|
||||||
|
if (word.length() == 36) {
|
||||||
|
var uuid = UUID.fromString(word);
|
||||||
|
return Bukkit.getPlayer(uuid);
|
||||||
|
} else {
|
||||||
|
return Bukkit.getPlayerExact(word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final ArgumentType<OfflinePlayer> offlinePlayer = new ArgumentType<>() {
|
||||||
|
@Override
|
||||||
|
public OfflinePlayer parseInput(ArgumentReader reader) {
|
||||||
|
final var str = reader.readWord();
|
||||||
|
OfflinePlayer player;
|
||||||
|
|
||||||
|
player = Bukkit.getPlayerExact(str);
|
||||||
|
if (player == null) {
|
||||||
|
try {
|
||||||
|
player = Bukkit.getOfflinePlayer(UUID.fromString(str));
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
throw new CommandInvocationException("Not a UUID or name of an online player");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDefaultSuggestions(CommandContext ctx) {
|
||||||
|
return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkValue(CommandContext ctx, OfflinePlayer value) throws CommandInvocationException {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static ArgumentType<Player> player() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArgumentType<OfflinePlayer> offlinePlayer() {
|
||||||
|
return offlinePlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.util.command;
|
|
||||||
|
|
||||||
import com.mojang.brigadier.LiteralMessage;
|
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class PlayerArgument {
|
|
||||||
|
|
||||||
public static Player resolve(CommandContext<Object> ctx, String argumentName) throws CommandSyntaxException {
|
|
||||||
var str = ctx.getArgument(argumentName, String.class);
|
|
||||||
boolean isUUID = str.length() == 36;
|
|
||||||
return isUUID ? Bukkit.getPlayer(parseUUID(str)) : Bukkit.getPlayerExact(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UUID parseUUID(String string) throws CommandSyntaxException {
|
|
||||||
try {
|
|
||||||
return UUID.fromString(string);
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
throw new SimpleCommandExceptionType(new LiteralMessage("Invalid UUID")).create();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package de.kentoj.scrow.bukkit;
|
package de.kentoj.scrow.bukkit;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.friends.command.LaunchCommand;
|
import de.kentoj.scrow.bukkit.economy.command.CoinsCommand;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ public class CoreImplPlugin extends JavaPlugin {
|
||||||
ScrowAPISurface.initScrowAPI(this, false);
|
ScrowAPISurface.initScrowAPI(this, false);
|
||||||
|
|
||||||
{
|
{
|
||||||
ScrowAPI.getCommandManager().register(new LaunchCommand(), this);
|
ScrowAPI.getCommandManager().register(new CoinsCommand().create(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import com.mongodb.ConnectionString;
|
||||||
import com.mongodb.MongoClientSettings;
|
import com.mongodb.MongoClientSettings;
|
||||||
import com.mongodb.reactivestreams.client.MongoClient;
|
import com.mongodb.reactivestreams.client.MongoClient;
|
||||||
import com.mongodb.reactivestreams.client.MongoClients;
|
import com.mongodb.reactivestreams.client.MongoClients;
|
||||||
import de.kentoj.scrow.bukkit.command.bukkit.CommandManagerImpl;
|
import de.kentoj.scrow.bukkit.cmds2.CommandFactoryImpl;
|
||||||
import de.kentoj.scrow.bukkit.command.node.CommandNodeFactoryImpl;
|
import de.kentoj.scrow.bukkit.cmds2.CommandManagerImpl;
|
||||||
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
|
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
|
||||||
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
|
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeRepository;
|
import de.kentoj.scrow.bukkit.services.command.cmds2.Commands;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.bson.UuidRepresentation;
|
import org.bson.UuidRepresentation;
|
||||||
|
|
@ -48,7 +48,7 @@ public class ScrowAPISurface {
|
||||||
new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService()
|
new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService()
|
||||||
);
|
);
|
||||||
|
|
||||||
CommandNodeRepository.setCommandNodeFactory(new CommandNodeFactoryImpl());
|
Commands.setFactory(new CommandFactoryImpl());
|
||||||
ScrowAPI.setCommandManager(new CommandManagerImpl());
|
ScrowAPI.setCommandManager(new CommandManagerImpl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.cmds2;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.node.ArgumentCommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.node.CommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.node.LiteralCommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootCommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class BukkitCommand extends Command {
|
|
||||||
|
|
||||||
private final RootCommandNode rootCommandNode;
|
|
||||||
|
|
||||||
protected BukkitCommand(RootCommandNode rootCommandNode) {
|
|
||||||
super(rootCommandNode.getName());
|
|
||||||
this.rootCommandNode = rootCommandNode;
|
|
||||||
|
|
||||||
if (rootCommandNode.getDescription() != null) {
|
|
||||||
super.setDescription(rootCommandNode.getDescription());
|
|
||||||
}
|
|
||||||
if (rootCommandNode.getAliases() != null) {
|
|
||||||
super.setAliases(rootCommandNode.getAliases().stream().toList());
|
|
||||||
}
|
|
||||||
// TODO usage string?
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processCommand(@NotNull CommandSender sender, @NotNull String commandLabel,
|
|
||||||
@NotNull String[] args) throws CommandSyntaxException {
|
|
||||||
CommandNode node = rootCommandNode;
|
|
||||||
int argsIndex = 0;
|
|
||||||
|
|
||||||
while (node.hasNextNode()) {
|
|
||||||
if (args.length - 1 < argsIndex) {
|
|
||||||
if (node)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node instanceof LiteralCommandNode literal) {
|
|
||||||
|
|
||||||
node = literal.getSubNode(args[argsIndex]);
|
|
||||||
if (node == null) {
|
|
||||||
throw new CommandSyntaxException("Invalid argument -- " + args[argsIndex])
|
|
||||||
}
|
|
||||||
} else if (node instanceof ArgumentCommandNode) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
argsIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.cmds2;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.ScrowAPI;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.node.ArgumentCommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.cmds2.node.LiteralCommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.EntityArgumentType;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import reactor.core.scheduler.Schedulers;
|
|
||||||
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
@SuppressWarnings("DataFlowIssue")
|
|
||||||
public class CoinsCommand implements CommandExecutor {
|
|
||||||
|
|
||||||
public CoinsCommand() {
|
|
||||||
final ArgumentCommandNode node = null;
|
|
||||||
node.addArgument("player", EntityArgumentType.player(), CommandContext::getSenderPlayer);
|
|
||||||
node.setExecutor(this::displayCoins);
|
|
||||||
|
|
||||||
final LiteralCommandNode setLiteral;
|
|
||||||
node.addSubNode(setLiteral);
|
|
||||||
setLiteral
|
|
||||||
{
|
|
||||||
final ArgumentCommandNode specifyPlayerNode = null /* TODO */;
|
|
||||||
|
|
||||||
node.addSubNode(specifyPlayerNode);
|
|
||||||
specifyPlayerNode.addArgument("player", EntityArgumentType.player(), CommandContext::getSenderPlayer);
|
|
||||||
specifyPlayerNode.setExecutor(this::setCoins);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayCoins(CommandContext ctx) {
|
|
||||||
final Player player = ctx.getArg("player");
|
|
||||||
|
|
||||||
ScrowAPI.getEconomyService()
|
|
||||||
.getCoins(player.getUniqueId())
|
|
||||||
.subscribeOn(Schedulers.boundedElastic())
|
|
||||||
.publishOn(ScrowAPI.getMinecraftScheduler())
|
|
||||||
.subscribe(coins -> {
|
|
||||||
player.sendMessage("You have " + coins + "$");
|
|
||||||
}, err -> {
|
|
||||||
player.sendMessage("Error fetching coins: " + err.getMessage());
|
|
||||||
Bukkit.getLogger().log(Level.SEVERE, "Failed fetching coins for " + player.getUniqueId(), err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCoins(CommandContext ctx) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandContextImpl implements CommandContext {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final CommandSender sender;
|
||||||
|
private final Map<String, ?> arguments;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getArg(String name) {
|
||||||
|
final T value = (T) arguments.get(name);
|
||||||
|
Preconditions.checkState(value != null, "no value for '" + name + "'-argument");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Player getSenderPlayer() {
|
||||||
|
if (!(sender instanceof Player)) throw new CommandInvocationException("This command can only be used by players");
|
||||||
|
return (Player) sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity getSenderEntity() {
|
||||||
|
if (!(sender instanceof Entity)) throw new CommandInvocationException("This command can only be used by entities");
|
||||||
|
return (Entity) sender;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.cmds2.types.CommandArgumentImpl;
|
||||||
|
import de.kentoj.scrow.bukkit.cmds2.types.LiteralImpl;
|
||||||
|
import de.kentoj.scrow.bukkit.cmds2.types.RootLiteralImpl;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandArgument;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandFactory;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.Literal;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class CommandFactoryImpl implements CommandFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Literal literal(String name) {
|
||||||
|
return new LiteralImpl(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RootLiteral root(String name) {
|
||||||
|
return new RootLiteralImpl(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> CommandArgument<T> argument(String name, ArgumentType<T> type, Function<CommandContext, T> defaultValueFun) {
|
||||||
|
return new CommandArgumentImpl<>(name, type, defaultValueFun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package de.kentoj.scrow.bukkit.command.bukkit;
|
package de.kentoj.scrow.bukkit.cmds2;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.cmds2.parsing.BukkitCommand;
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandManager;
|
import de.kentoj.scrow.bukkit.services.command.CommandManager;
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandMap;
|
import org.bukkit.command.CommandMap;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
|
@ -22,18 +22,8 @@ public class CommandManagerImpl implements CommandManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(CommandNode rootCommandNode, Plugin plugin) {
|
public void register(RootLiteral rootLiteral, Plugin plugin) {
|
||||||
var bukkitCommand = toBukkitCommand(rootCommandNode);
|
var bukkitCommand = new BukkitCommand(rootLiteral);
|
||||||
commandMap.register(plugin.getName(), bukkitCommand);
|
commandMap.register(plugin.getName(), bukkitCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Command toBukkitCommand(CommandNode commandNode) {
|
|
||||||
return new BukkitCommand(
|
|
||||||
commandNode,
|
|
||||||
commandNode.getName(),
|
|
||||||
commandNode.getDescription(),
|
|
||||||
"",
|
|
||||||
commandNode.getAliases()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.parsing;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.ArgumentReader;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
|
||||||
|
public class ArgumentReaderImpl implements ArgumentReader {
|
||||||
|
|
||||||
|
private final CharBuffer buf;
|
||||||
|
|
||||||
|
public ArgumentReaderImpl(String string) {
|
||||||
|
buf = CharBuffer.wrap(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentReaderImpl(String[] args) {
|
||||||
|
this(String.join(" ", args));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEOF() {
|
||||||
|
return buf.position() >= buf.limit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readWord() {
|
||||||
|
final var str = new StringBuilder();
|
||||||
|
while (true) {
|
||||||
|
if (buf.position() >= buf.limit()) break;
|
||||||
|
char c = buf.get();
|
||||||
|
if (c == ' ') break;
|
||||||
|
str.append(c);
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readQuotedWord() {
|
||||||
|
final var str = new StringBuilder();
|
||||||
|
var quoting = false;
|
||||||
|
while (true) {
|
||||||
|
if (buf.position() >= buf.limit()) break;
|
||||||
|
char c = buf.get();
|
||||||
|
if (c == '"') quoting = !quoting;
|
||||||
|
if (c == ' ' && !quoting) break;
|
||||||
|
str.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quoting) throw new CommandInvocationException("Missing matching \" to terminate quote");
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCursor() {
|
||||||
|
return buf.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCursor(int cursor) {
|
||||||
|
buf.position(cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.parsing;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class BukkitCommand extends Command {
|
||||||
|
|
||||||
|
private final RootLiteral rootLiteral;
|
||||||
|
|
||||||
|
public BukkitCommand(RootLiteral rootLiteral) {
|
||||||
|
super(rootLiteral.getName());
|
||||||
|
this.rootLiteral = rootLiteral;
|
||||||
|
|
||||||
|
if (rootLiteral.getDescription() != null) {
|
||||||
|
super.setDescription(rootLiteral.getDescription());
|
||||||
|
}
|
||||||
|
if (rootLiteral.getAliases() != null) {
|
||||||
|
super.setAliases(rootLiteral.getAliases().stream().toList());
|
||||||
|
}
|
||||||
|
// TODO usage string?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
||||||
|
try {
|
||||||
|
new CommandProcessor(sender, new ArgumentReaderImpl(args)).execute(rootLiteral);
|
||||||
|
} catch (CommandInvocationException syntaxException) {
|
||||||
|
sender.sendMessage(ChatColor.RED + syntaxException.getMessage());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.parsing;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BukkitTabCompleter implements TabCompleter {
|
||||||
|
|
||||||
|
private final RootLiteral rootLiteral;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||||
|
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.parsing;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.cmds2.CommandContextImpl;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.ArgumentReader;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandArgument;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.Literal;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.exception.CommandInvocationException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandProcessor {
|
||||||
|
|
||||||
|
private final Map<String, Object> arguments = new HashMap<>();
|
||||||
|
|
||||||
|
private final CommandSender sender;
|
||||||
|
private final ArgumentReader argumentReader;
|
||||||
|
|
||||||
|
public void execute(RootLiteral rootLiteral) {
|
||||||
|
Literal lastLiteral = rootLiteral;
|
||||||
|
do {
|
||||||
|
processArguments(lastLiteral);
|
||||||
|
|
||||||
|
if (argumentReader.isEOF()) {
|
||||||
|
if (lastLiteral.getExecutor() == null) throw new CommandInvocationException("Incomplete command -- literal expected");
|
||||||
|
lastLiteral.getExecutor().execute(new CommandContextImpl(sender, arguments));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final var literalName = argumentReader.readWord();
|
||||||
|
lastLiteral = lastLiteral.getLiteral(literalName);
|
||||||
|
if (lastLiteral == null) throw new CommandInvocationException("Unknown literal -- " + literalName);
|
||||||
|
|
||||||
|
final boolean hasSenderPermission = lastLiteral.getRequiredPermission() == null || sender.hasPermission(lastLiteral.getRequiredPermission());
|
||||||
|
if (!hasSenderPermission) throw new CommandInvocationException("No permission");
|
||||||
|
} while (lastLiteral.hasLiteral());
|
||||||
|
|
||||||
|
processArguments(lastLiteral);
|
||||||
|
|
||||||
|
if (lastLiteral.getExecutor() == null) throw new CommandInvocationException("Incomplete command.");
|
||||||
|
lastLiteral.getExecutor().execute(new CommandContextImpl(sender, arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processArguments(Literal node) {
|
||||||
|
node.getArguments().forEach(arg -> {
|
||||||
|
Object parsed = parseArgument(arg);
|
||||||
|
arguments.put(arg.getName(), parsed);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Object parseArgument(CommandArgument<T> argument) {
|
||||||
|
if (argumentReader.isEOF()) {
|
||||||
|
var defaultValue = argument.getDefaultValue(new CommandContextImpl(sender, arguments));
|
||||||
|
if (defaultValue == null) throw new CommandInvocationException("Missing argument -- " + argument.getName());
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
T value = argument.getType().parseInput(argumentReader);
|
||||||
|
argument.getType().checkValue(new CommandContextImpl(sender, arguments), value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.types;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandArgument;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.SuggestionProvider;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandArgumentImpl<T> implements CommandArgument<T> {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final ArgumentType<T> type;
|
||||||
|
private final Function<CommandContext, T> defaultValueFun;
|
||||||
|
@Setter
|
||||||
|
private @Nullable SuggestionProvider suggestionProvider;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable T getDefaultValue(CommandContext ctx) {
|
||||||
|
return defaultValueFun.apply(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuggestionProvider getSuggestionProvider() {
|
||||||
|
if (suggestionProvider == null)
|
||||||
|
return type::getDefaultSuggestions;
|
||||||
|
return suggestionProvider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.types;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandArgument;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.Literal;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.permissions.Permission;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class LiteralImpl implements Literal {
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private @Nullable Permission requiredPermission = null;
|
||||||
|
@Setter
|
||||||
|
private @Nullable String description = null;
|
||||||
|
@Setter
|
||||||
|
private @Nullable CommandExecutor executor = null;
|
||||||
|
private final List<CommandArgument<?>> arguments = new ArrayList<>();
|
||||||
|
private final Map<String, Literal> literals = new HashMap<>();
|
||||||
|
|
||||||
|
public LiteralImpl(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLiteral(Literal node) {
|
||||||
|
if (literals.containsKey(node.getName())) {
|
||||||
|
Bukkit.getLogger().warning("Literal " + node.getName() + " is overwritten by literal with same name");
|
||||||
|
}
|
||||||
|
literals.put(node.getName(), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Literal getLiteral(String name) {
|
||||||
|
return literals.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLiteral() {
|
||||||
|
return !literals.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void addArgument(CommandArgument<T> argument) {
|
||||||
|
arguments.add(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.kentoj.scrow.bukkit.cmds2.types;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class RootLiteralImpl extends LiteralImpl implements RootLiteral {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Set<String> aliases = new HashSet<>();
|
||||||
|
|
||||||
|
public RootLiteralImpl(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAliases(String... aliases) {
|
||||||
|
this.aliases.addAll(List.of(aliases));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class CommandContextImpl implements CommandContext {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final CommandSender sender;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Player getSenderPlayer() {
|
|
||||||
return (Player) sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entity getSenderEntity() {
|
|
||||||
return (Entity) sender;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.command.bukkit.ArgumentData;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandArgument;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class CommandExecutionContextImpl extends CommandContextImpl implements CommadContext {
|
|
||||||
|
|
||||||
private final Map<String, ArgumentData> argumentDataMap;
|
|
||||||
|
|
||||||
public CommandExecutionContextImpl(CommandSender sender, Map<String, ArgumentData> argumentDataMap) {
|
|
||||||
super(sender);
|
|
||||||
this.argumentDataMap = argumentDataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String getRawArgument(String key) {
|
|
||||||
var data = argumentDataMap.get(key);
|
|
||||||
if (data.getRawValue() == null) {
|
|
||||||
if (data.getArgument().getDefaultValue() == null) {
|
|
||||||
throw new CommandSyntaxException("usage: missing arg value for " + key);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return data.getRawValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> T getArg(String key) {
|
|
||||||
var data = argumentDataMap.get(key);
|
|
||||||
var arg = (CommandArgument<T>) data.getArgument();
|
|
||||||
var raw = getRawArgument(key);
|
|
||||||
|
|
||||||
T value;
|
|
||||||
if (raw != null) {
|
|
||||||
value = arg.getType().parseInput(raw);
|
|
||||||
} else {
|
|
||||||
value = arg.getDefaultValue().apply(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
arg.getType().checkValue(this, value, raw);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.bukkit;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandArgument;
|
|
||||||
import lombok.Value;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
public class ArgumentData {
|
|
||||||
CommandArgument<?> argument;
|
|
||||||
@Nullable String rawValue;
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.bukkit;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class BukkitCommand extends Command {
|
|
||||||
|
|
||||||
private final CommandNode rootCommandNode;
|
|
||||||
|
|
||||||
protected BukkitCommand(CommandNode rootCommandNode, @NotNull String name, @NotNull String description, @NotNull String usageMessage, @NotNull Set<String> aliases) {
|
|
||||||
super(name, description, usageMessage, aliases.stream().toList());
|
|
||||||
this.rootCommandNode = rootCommandNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
|
||||||
final var commandProcessor = new CommandProcessor(rootCommandNode, sender, args);
|
|
||||||
|
|
||||||
try {
|
|
||||||
commandProcessor.process();
|
|
||||||
} catch (CommandSyntaxException e) {
|
|
||||||
sender.sendMessage("error: " + e.getMessage());
|
|
||||||
return true;
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
throw new RuntimeException("failed processing command " + rootCommandNode.getName(), e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.bukkit;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.command.CommandExecutionContextImpl;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandArgument;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.exception.CommandSyntaxException;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithArguments;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithSubCommand;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class CommandProcessor {
|
|
||||||
|
|
||||||
private final Map<String, ArgumentData> argumentDataMap = new HashMap<>();
|
|
||||||
|
|
||||||
private CommandNode node;
|
|
||||||
private final CommandSender sender;
|
|
||||||
private final String[] args;
|
|
||||||
|
|
||||||
public void process() throws CommandSyntaxException {
|
|
||||||
for (int cursor = 0; true; cursor++) {
|
|
||||||
if (args.length - 1 < cursor) {
|
|
||||||
if (node.getExecutor() == null) throw new CommandSyntaxException("Incomplete command");
|
|
||||||
execute(node.getExecutor());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node instanceof CommandNodeWithArguments nodeWA) {
|
|
||||||
final var arg = nodeWA.getArg(cursor);
|
|
||||||
assert arg != null;
|
|
||||||
final var data = new ArgumentData(arg, args[cursor]);
|
|
||||||
argumentDataMap.put(arg.getName(), data);
|
|
||||||
} else if (node instanceof CommandNodeWithSubCommand nodeWS) {
|
|
||||||
if (nodeWS.getSubCommands().isEmpty()) break;
|
|
||||||
final var subcommand = nodeWS.getSubCommand(args[cursor]);
|
|
||||||
if (subcommand == null) {
|
|
||||||
final var subcommands = nodeWS.getSubCommands().stream().map(CommandNode::getName).toList();
|
|
||||||
throw new CommandSyntaxException("Illegal argument -- " + args[cursor] + "\nExpected arguments: " + String.join(", ", subcommands));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.node = nodeWS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.getExecutor() == null) throw new IllegalStateException("Last CommandNode must have an executor");
|
|
||||||
execute(node.getExecutor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void execute(CommandExecutor executor) {
|
|
||||||
var ctx = new CommandExecutionContextImpl(sender, argumentDataMap);
|
|
||||||
executor.execute(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeFactory;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithArguments;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithSubCommand;
|
|
||||||
|
|
||||||
public class CommandNodeFactoryImpl implements CommandNodeFactory {
|
|
||||||
@Override
|
|
||||||
public CommandNodeWithSubCommand createNodeWithSubCommands(String name) {
|
|
||||||
return new CommandNodeWithSubCommandImpl(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandNodeWithArguments createNodeWithArguments(String name) {
|
|
||||||
return new CommandNodeWithArgumentsImpl(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandNode createRootNode(String name) {
|
|
||||||
return new CommandNodeImpl(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.bukkit.permissions.Permission;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class CommandNodeImpl implements CommandNode {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
private Set<String> aliases = new HashSet<>();
|
|
||||||
@Setter
|
|
||||||
private @Nullable Permission permission = null;
|
|
||||||
@Setter
|
|
||||||
private @Nullable String description;
|
|
||||||
@Setter
|
|
||||||
private @Nullable CommandExecutor executor = null;
|
|
||||||
|
|
||||||
public CommandNodeImpl(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAlias(String... aliases) {
|
|
||||||
this.aliases.addAll(Arrays.asList(aliases));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.node;
|
|
||||||
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandArgument;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithArguments;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.ArgumentType;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class CommandNodeWithArgumentsImpl extends CommandNodeImpl implements CommandNodeWithArguments {
|
|
||||||
|
|
||||||
private final List<CommandArgument<?>> args = new ArrayList<>();
|
|
||||||
|
|
||||||
public CommandNodeWithArgumentsImpl(String name) {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void addArg(String name, ArgumentType<T> type, Function<CommandContext, T> defaultValue) {
|
|
||||||
var index = args.size();
|
|
||||||
if (index > 0) {
|
|
||||||
boolean isPreviousArgumentOptional = args.get(index - 1).getDefaultValue() != null;
|
|
||||||
boolean isNewArgumentOptional = defaultValue != null;
|
|
||||||
if (isPreviousArgumentOptional && !isNewArgumentOptional) {
|
|
||||||
throw new IllegalStateException("an optional argument(an argument with a defaultValue set) may not be followed by a required argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args.add(new CommandArgument<>(index, name, type, defaultValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable CommandArgument<?> getArg(String name) {
|
|
||||||
return args.stream()
|
|
||||||
.filter(ra -> ra.getName().equals(name))
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable CommandArgument<?> getArg(int index) {
|
|
||||||
return args.stream()
|
|
||||||
.filter(ra -> ra.getIndex() == index)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.command.node;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithSubCommand;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class CommandNodeWithSubCommandImpl extends CommandNodeImpl implements CommandNodeWithSubCommand {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final List<CommandNode> subCommands = new ArrayList<>();
|
|
||||||
|
|
||||||
public CommandNodeWithSubCommandImpl(String name) {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addSubCommand(CommandNode subCommand) {
|
|
||||||
subCommands.add(subCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable CommandNode getSubCommand(String label) {
|
|
||||||
return subCommands.stream()
|
|
||||||
.filter(n -> n.getName().equals(label) || n.getAliases().contains(label))
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -14,6 +14,7 @@ import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
// TODO log
|
||||||
public class MongoEconomyService implements EconomyService {
|
public class MongoEconomyService implements EconomyService {
|
||||||
|
|
||||||
private static final String COLLECTION_NAME = "economy";
|
private static final String COLLECTION_NAME = "economy";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package de.kentoj.scrow.bukkit.economy.command;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandArgument;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.CommandContext;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.Commands;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.cmds2.node.RootLiteral;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.type.NumberArgumentType;
|
||||||
|
import de.kentoj.scrow.bukkit.services.command.type.PlayerArgumentType;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class CoinsCommand {
|
||||||
|
|
||||||
|
private final RootLiteral rootCommand;
|
||||||
|
private final CommandArgument<OfflinePlayer> playerArg;
|
||||||
|
private final CommandArgument<Integer> amountArg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
/coins steve
|
||||||
|
/coins steve set 0
|
||||||
|
/coins steve get
|
||||||
|
*/
|
||||||
|
public CoinsCommand() {
|
||||||
|
playerArg = Commands.argument0("player", PlayerArgumentType.offlinePlayer(), CommandContext::getSenderPlayer);
|
||||||
|
|
||||||
|
amountArg = Commands.argument0("amount", NumberArgumentType.integer(0, Integer.MAX_VALUE));
|
||||||
|
|
||||||
|
rootCommand = Commands.root("coins");
|
||||||
|
rootCommand.addArgument(playerArg);
|
||||||
|
rootCommand.setExecutor(this::getCoins);
|
||||||
|
{
|
||||||
|
final var setLiteral = Commands.literal("set");
|
||||||
|
setLiteral.addArgument(amountArg);
|
||||||
|
setLiteral.setExecutor(this::setCoins);
|
||||||
|
rootCommand.addLiteral(setLiteral);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
final var getLiteral = Commands.literal("get");
|
||||||
|
getLiteral.setExecutor(this::getCoins);
|
||||||
|
rootCommand.addLiteral(getLiteral);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RootLiteral create() {
|
||||||
|
return rootCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getCoins(CommandContext ctx) {
|
||||||
|
final var player = ctx.getArg(playerArg);
|
||||||
|
|
||||||
|
ScrowAPI.getEconomyService()
|
||||||
|
.getCoins(player.getUniqueId())
|
||||||
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
|
.publishOn(ScrowAPI.getMinecraftScheduler())
|
||||||
|
.subscribe(amount -> {
|
||||||
|
if (player == ctx.getSender()) {
|
||||||
|
ctx.getSender().sendMessage("You have " + amount + "$");
|
||||||
|
} else {
|
||||||
|
ctx.getSender().sendMessage(player.getName() + " has " + amount + "$");
|
||||||
|
}
|
||||||
|
}, err -> {
|
||||||
|
ctx.getSender().sendMessage("Unable to get coins: " + err.getMessage());
|
||||||
|
Bukkit.getLogger().log(Level.SEVERE, "Unable to get coins of " + player.getUniqueId(), err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCoins(CommandContext ctx) {
|
||||||
|
final var player = ctx.getArg(playerArg);
|
||||||
|
final int amount = ctx.getArg(amountArg);
|
||||||
|
|
||||||
|
ScrowAPI.getEconomyService()
|
||||||
|
.setCoins(player.getUniqueId(), amount)
|
||||||
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
|
.publishOn(ScrowAPI.getMinecraftScheduler())
|
||||||
|
.subscribe(__ -> {
|
||||||
|
ctx.getSender().sendMessage(player.getName() + " now has " + amount + "$");
|
||||||
|
}, err -> {
|
||||||
|
ctx.getSender().sendMessage("Unable to set coins: " + err.getMessage());
|
||||||
|
Bukkit.getLogger().log(Level.SEVERE, "Unable to set coins of " + player.getUniqueId() + " to " + amount, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.friends.command;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeRepository;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.node.CommandNodeWithSubCommand;
|
|
||||||
|
|
||||||
public class FriendCommand {
|
|
||||||
|
|
||||||
private final CommandNodeWithSubCommand node = CommandNodeRepository.withSubCommands("friend");
|
|
||||||
|
|
||||||
public FriendCommand() {
|
|
||||||
this.node.addAlias("f");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.friends.command;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.command.node.CommandNodeWithArgumentsImpl;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.CommandExecutor;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.context.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.services.command.type.EntityArgumentType;
|
|
||||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.permissions.Permission;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
public class LaunchCommand extends CommandNodeWithArgumentsImpl implements CommandExecutor {
|
|
||||||
|
|
||||||
public LaunchCommand() {
|
|
||||||
super("launch");
|
|
||||||
this.setDescription("launches a player in the air");
|
|
||||||
this.setPermission(new Permission("bukkitcore.cmd.launch"));
|
|
||||||
|
|
||||||
this.addArg("player", EntityArgumentType.player(), CommandContext::getSenderPlayer);
|
|
||||||
this.setExecutor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandExecutionContext ctx) {
|
|
||||||
final Player player = ctx.getArg("player");
|
|
||||||
player.spigot().sendMessage(new TranslatableComponent(""));
|
|
||||||
player.setVelocity(new Vector(0, 2, 0));
|
|
||||||
player.sendMessage("Launched " + player.getName() + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue