.
This commit is contained in:
parent
254af80fde
commit
72f7625b19
53 changed files with 679 additions and 756 deletions
|
|
@ -1,62 +1,8 @@
|
||||||
val scrowToken = providers.gradleProperty("scrowMavenToken")
|
|
||||||
.orElse(providers.environmentVariable("SCROW_MAVEN_TOKEN")).get()
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id("java")
|
|
||||||
id("io.freefair.lombok") version "9.2.0" apply false
|
|
||||||
}
|
|
||||||
|
|
||||||
group = "de.kentoj.scrow"
|
group = "de.kentoj.scrow"
|
||||||
version = "0.9"
|
version = "0.10"
|
||||||
|
|
||||||
fun RepositoryHandler.scrowRepo() = maven {
|
|
||||||
name = "scrow"
|
|
||||||
url = uri("http://forge.kentoj.de/api/packages/scrow/maven")
|
|
||||||
isAllowInsecureProtocol = true
|
|
||||||
credentials(HttpHeaderCredentials::class) {
|
|
||||||
name = "Authorization"
|
|
||||||
value = "token $scrowToken"
|
|
||||||
}
|
|
||||||
authentication {
|
|
||||||
create<HttpHeaderAuthentication>("header")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply(plugin = "java")
|
group = rootProject.group
|
||||||
apply(plugin = "maven-publish")
|
version = rootProject.version
|
||||||
apply(plugin = "io.freefair.lombok")
|
|
||||||
|
|
||||||
java {
|
|
||||||
withSourcesJar()
|
|
||||||
withJavadocJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<Javadoc>().configureEach {
|
|
||||||
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:all,-missing", "-quiet")
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
scrowRepo()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains/annotations
|
|
||||||
implementation("org.jetbrains:annotations:26.0.2-1")
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<PublishingExtension> {
|
|
||||||
publications {
|
|
||||||
create<MavenPublication>("KenCommandAPI") {
|
|
||||||
groupId = rootProject.group.toString()
|
|
||||||
version = rootProject.version.toString()
|
|
||||||
artifactId = project.name
|
|
||||||
from(components["java"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
scrowRepo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
plugins {
|
plugins {
|
||||||
id("java")
|
id("java")
|
||||||
id("java-library")
|
id("maven-publish")
|
||||||
|
id("de.kentoj.scrow.scrow-repository")
|
||||||
|
id("de.kentoj.scrow.base-dependencies")
|
||||||
|
id("de.kentoj.scrow.java-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "de.kentoj"
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
|
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
|
||||||
name = "spigotmc-repo"
|
name = "spigotmc-repo"
|
||||||
|
|
@ -16,3 +16,14 @@ dependencies {
|
||||||
api(project(":kencommandapi-core"))
|
api(project(":kencommandapi-core"))
|
||||||
compileOnly("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
compileOnly("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("KenCommandAPI") {
|
||||||
|
groupId = rootProject.group.toString()
|
||||||
|
version = rootProject.version.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
from(components["java"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package de.kentoj.kencommandapi;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.impl.processing.CommandContextImpl;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class BukkitCommandContext extends CommandContextImpl<CommandSender, BukkitCommandContext> {
|
|
||||||
|
|
||||||
BukkitCommandContext(
|
|
||||||
CommandSender sender,
|
|
||||||
Map<String, ParsedArgument<CommandSender, BukkitCommandContext, ?>> parsedArguments
|
|
||||||
) {
|
|
||||||
super(sender, parsedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Player getPlayerSender() {
|
|
||||||
return ((Player) getSender());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package de.kentoj.kencommandapi;
|
package de.kentoj.kencommandapi;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.KenCommandApi;
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||||
|
import de.kentoj.kencommandapi.internal.parser.CommandParser;
|
||||||
|
import de.kentoj.kencommandapi.internal.parser.ParseResult;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -10,23 +12,37 @@ import java.util.Arrays;
|
||||||
|
|
||||||
public class BukkitKenCommand extends Command {
|
public class BukkitKenCommand extends Command {
|
||||||
|
|
||||||
private final CommandNode<CommandSender, BukkitCommandContext> rootNode;
|
private final CommandNode<CommandSender> rootNode;
|
||||||
private final KenCommandApi<CommandSender, BukkitCommandContext> commandManager;
|
private final CommandParser<CommandSender> commandParser;
|
||||||
|
|
||||||
protected BukkitKenCommand(
|
protected BukkitKenCommand(
|
||||||
KenCommandApi<CommandSender, BukkitCommandContext> commandManager,
|
CommandParser<CommandSender> commandParser,
|
||||||
CommandNode<CommandSender, BukkitCommandContext> rootNode
|
CommandNode<CommandSender> rootNode
|
||||||
) {
|
) {
|
||||||
super(rootNode.getNames()[0]);
|
super(rootNode.getNames()[0]);
|
||||||
|
this.commandParser = commandParser;
|
||||||
this.rootNode = rootNode;
|
this.rootNode = rootNode;
|
||||||
this.commandManager = commandManager;
|
|
||||||
this.setAliases(Arrays.asList(rootNode.getNames()));
|
this.setAliases(Arrays.asList(rootNode.getNames()));
|
||||||
this.setPermission(rootNode.getPermission());
|
this.setPermission(rootNode.getPermission());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
||||||
commandManager.invoke(rootNode, sender, args);
|
var parseResult = commandParser.parseLiteral(rootNode, sender, args);
|
||||||
return false;
|
if (parseResult instanceof ParseResult.Success<CommandSender>) {
|
||||||
|
var ctx = new CommandContext<>(sender, ((ParseResult.Success<CommandSender>) parseResult).getParsedArguments());
|
||||||
|
assert parseResult.getLiteral().getExecutor() != null;
|
||||||
|
try {
|
||||||
|
var result = parseResult.getLiteral().getExecutor().execute(ctx);
|
||||||
|
if (result.isError()) {
|
||||||
|
sender.sendMessage("§c" + result.getError());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
sender.sendMessage("§4§lERROR " + e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("§c" + parseResult.getMessage());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
package de.kentoj.kencommandapi;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
|
||||||
import de.kentoj.kencommandapi.impl.AbstractKenCommandApi;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.SimpleCommandMap;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class BukkitKenCommandApi extends AbstractKenCommandApi<CommandSender, BukkitCommandContext> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BukkitCommandContext createContext(
|
|
||||||
CommandSender sender,
|
|
||||||
Map<String, ParsedArgument<CommandSender, BukkitCommandContext, ?>> parsedArguments
|
|
||||||
) {
|
|
||||||
return new BukkitCommandContext(sender, parsedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendErrorMessage(CommandSender sender, CommandException ex) {
|
|
||||||
var cause = (ex.getCause() != null) ? ": " + ex.getCause().getMessage() : "";
|
|
||||||
sender.sendMessage("§c" + ex.getMessage() + cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(CommandSender sender, String permission) {
|
|
||||||
return sender.hasPermission(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(CommandNode<CommandSender, BukkitCommandContext> rootNode) {
|
|
||||||
try {
|
|
||||||
Field field = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
|
|
||||||
field.setAccessible(true);
|
|
||||||
SimpleCommandMap commandMap = (SimpleCommandMap) field.get(Bukkit.getPluginManager());
|
|
||||||
commandMap.register(rootNode.getNames()[0], new BukkitKenCommand(this, rootNode));
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package de.kentoj.kencommandapi;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
|
import de.kentoj.kencommandapi.internal.parser.CommandParser;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.SimpleCommandMap;
|
||||||
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public class CommandAPI {
|
||||||
|
|
||||||
|
private final CommandParser<CommandSender> commandParser = new CommandParser<>(Permissible::hasPermission);
|
||||||
|
|
||||||
|
public void register(CommandNode<CommandSender> rootNode) {
|
||||||
|
SimpleCommandMap commandMap;
|
||||||
|
try {
|
||||||
|
Field field = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
|
||||||
|
field.setAccessible(true);
|
||||||
|
commandMap = (SimpleCommandMap) field.get(Bukkit.getPluginManager());
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException("failed registering command ", e);
|
||||||
|
}
|
||||||
|
commandMap.register(rootNode.getNames()[0], new BukkitKenCommand(commandParser, rootNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package de.kentoj.kencommandapi.suggestionprovider;
|
package de.kentoj.kencommandapi.suggestionprovider;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.BukkitCommandContext;
|
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
@ -10,9 +10,9 @@ import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSender, BukkitCommandContext> {
|
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSender> {
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Set<String>> suggest(BukkitCommandContext context) {
|
public CompletableFuture<Set<String>> suggest(CommandContext<CommandSender> context) {
|
||||||
var list = Bukkit.getOnlinePlayers().stream()
|
var list = Bukkit.getOnlinePlayers().stream()
|
||||||
.map(Player::getName)
|
.map(Player::getName)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
package de.kentoj.kencommandapi.type;
|
package de.kentoj.kencommandapi.type;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.BukkitCommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
import de.kentoj.kencommandapi.api.argument.suggestion.NoSuggestionProvider;
|
|
||||||
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
|
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
@ -16,7 +13,7 @@ import org.bukkit.command.CommandSender;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class OfflinePlayerArgumentType implements ArgumentType<CommandSender, BukkitCommandContext, OfflinePlayer> {
|
public class OfflinePlayerArgumentType implements ArgumentType<CommandSender, OfflinePlayer> {
|
||||||
|
|
||||||
@Getter(lazy = true)
|
@Getter(lazy = true)
|
||||||
private static final OfflinePlayerArgumentType instance = new OfflinePlayerArgumentType();
|
private static final OfflinePlayerArgumentType instance = new OfflinePlayerArgumentType();
|
||||||
|
|
@ -29,15 +26,15 @@ public class OfflinePlayerArgumentType implements ArgumentType<CommandSender, Bu
|
||||||
try {
|
try {
|
||||||
player = Bukkit.getOfflinePlayer(UUID.fromString(string));
|
player = Bukkit.getOfflinePlayer(UUID.fromString(string));
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
throw new CommandException("Not a UUID or online player -- " + string);
|
throw new IllegalArgumentException("Not a UUID or online player -- " + string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!player.hasPlayedBefore() && !player.isOnline()) throw new CommandException("Unknown player -- " + string);
|
if (!player.hasPlayedBefore() && !player.isOnline()) throw new IllegalArgumentException("Unknown player -- " + string);
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SuggestionProvider<CommandSender, BukkitCommandContext> defaultSuggestionProvider() {
|
public SuggestionProvider<CommandSender> defaultSuggestionProvider() {
|
||||||
return new PlayerSuggestionProvider();
|
return new PlayerSuggestionProvider();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package de.kentoj.kencommandapi.type;
|
package de.kentoj.kencommandapi.type;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.BukkitCommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
|
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
@ -13,7 +11,7 @@ import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class PlayerArgumentType implements ArgumentType<CommandSender, BukkitCommandContext, Player> {
|
public class PlayerArgumentType implements ArgumentType<CommandSender, Player> {
|
||||||
|
|
||||||
@Getter(lazy = true)
|
@Getter(lazy = true)
|
||||||
private static final PlayerArgumentType instance = new PlayerArgumentType();
|
private static final PlayerArgumentType instance = new PlayerArgumentType();
|
||||||
|
|
@ -21,12 +19,12 @@ public class PlayerArgumentType implements ArgumentType<CommandSender, BukkitCom
|
||||||
@Override
|
@Override
|
||||||
public Player parseInput(String string) {
|
public Player parseInput(String string) {
|
||||||
var player = Bukkit.getPlayer(string);
|
var player = Bukkit.getPlayer(string);
|
||||||
if (player == null) throw new CommandException("Player not online -- " + string);
|
if (player == null) throw new IllegalArgumentException("Player not online -- " + string);
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SuggestionProvider<CommandSender, BukkitCommandContext> defaultSuggestionProvider() {
|
public SuggestionProvider<CommandSender> defaultSuggestionProvider() {
|
||||||
return new PlayerSuggestionProvider();
|
return new PlayerSuggestionProvider();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
kencommandapi-core/build.gradle.kts
Normal file
18
kencommandapi-core/build.gradle.kts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("maven-publish")
|
||||||
|
id("de.kentoj.scrow.scrow-repository")
|
||||||
|
id("de.kentoj.scrow.base-dependencies")
|
||||||
|
id("de.kentoj.scrow.java-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("KenCommandAPI") {
|
||||||
|
groupId = rootProject.group.toString()
|
||||||
|
version = rootProject.version.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
from(components["java"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package de.kentoj.kencommandapi;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.types.IntegerArgumentType;
|
|
||||||
import de.kentoj.kencommandapi.impl.AbstractKenCommandApi;
|
|
||||||
import de.kentoj.kencommandapi.impl.processing.CommandContextImpl;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Main {
|
|
||||||
|
|
||||||
private static class BasicCommandContext extends CommandContextImpl<PrintStream, BasicCommandContext> {
|
|
||||||
public BasicCommandContext(PrintStream sender, Map<String, ParsedArgument<PrintStream, BasicCommandContext, ?>> parsedArguments) {
|
|
||||||
super(sender, parsedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void respond(String msg) {
|
|
||||||
getSender().println("|==================|");
|
|
||||||
getSender().println(msg);
|
|
||||||
getSender().println("|==================|");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
var api = new AbstractKenCommandApi<PrintStream, BasicCommandContext>() {
|
|
||||||
@Override
|
|
||||||
public BasicCommandContext createContext(PrintStream sender, Map<String, ParsedArgument<PrintStream, BasicCommandContext, ?>> parsedArguments) {
|
|
||||||
return new BasicCommandContext(sender, parsedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendErrorMessage(PrintStream printStream, CommandException ex) {
|
|
||||||
System.err.println(ex.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(PrintStream printStream, String permission) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var root = api.createNode("coins");
|
|
||||||
|
|
||||||
var addNode = api.createNode("add", "deposit");
|
|
||||||
addNode.setExecutor(ctx -> {
|
|
||||||
int amount = ctx.getArg("amount");
|
|
||||||
|
|
||||||
ctx.respond("adding " + amount + "$ to your balance");
|
|
||||||
});
|
|
||||||
|
|
||||||
addNode.addArgument(api.createArgument("amount", new IntegerArgumentType<>()));
|
|
||||||
root.addLiteral(addNode);
|
|
||||||
api.invoke(root, System.out, new String[]{"add", "100"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package de.kentoj.kencommandapi.api;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||||
|
import de.kentoj.kencommandapi.internal.CommandNodeImpl;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface CommandNode<T> {
|
||||||
|
static <T> CommandNode<T> node(String... name) {
|
||||||
|
return new CommandNodeImpl<>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull String[] getNames();
|
||||||
|
|
||||||
|
void setDescription(@Nullable String description);
|
||||||
|
|
||||||
|
@Nullable String getDescription();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* arguments
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws IllegalArgumentException if there is already an argument with the same id
|
||||||
|
* @throws IllegalStateException if a greedy argument was added to the node previously
|
||||||
|
*/
|
||||||
|
<V> void addArgument(CommandArgument<T, V> argument);
|
||||||
|
|
||||||
|
List<CommandArgument<T, ?>> getArguments();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* literals
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setExecutor(@Nullable CommandExecutor<T> executor);
|
||||||
|
|
||||||
|
@Nullable CommandExecutor<T> getExecutor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws IllegalArgumentException if there is already a literal with the same name
|
||||||
|
* @throws IllegalStateException if a greedy argument was added to the node previously
|
||||||
|
*/
|
||||||
|
void addLiteral(@NotNull CommandNode<T> commandNode);
|
||||||
|
|
||||||
|
@Nullable CommandNode<T> getLiteral(@NotNull String name);
|
||||||
|
|
||||||
|
@NotNull Set<CommandNode<T>> getLiterals();
|
||||||
|
|
||||||
|
@Nullable String getPermission();
|
||||||
|
|
||||||
|
void setPermission(@Nullable String permission);
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
|
||||||
|
|
||||||
public interface KenCommandApi<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
CommandNode<T, S> createNode(String... name);
|
|
||||||
|
|
||||||
<V> CommandArgument<T, S, V> createArgument(String id, ArgumentType<T, S, V> type);
|
|
||||||
|
|
||||||
void invoke(CommandNode<T, S> node, T sender, String[] args);
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
package de.kentoj.kencommandapi.api.argument;
|
package de.kentoj.kencommandapi.api.argument;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
|
|
||||||
public interface ArgumentType<T, S extends CommandContext<T, ?>, V> {
|
public interface ArgumentType<T, V> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws IllegalArgumentException if string invalid
|
||||||
|
*/
|
||||||
V parseInput(String string);
|
V parseInput(String string);
|
||||||
|
|
||||||
SuggestionProvider<T, S> defaultSuggestionProvider();
|
SuggestionProvider<T> defaultSuggestionProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether this argument is greedy. Greedy arguments consume all remaining input instead of a single word.
|
||||||
|
* For example, given the 2 words "hello" "world" as input, a greedy argument parses "hello world" as a single value.
|
||||||
|
* Greedy arguments may not be followed by another argument or a literal
|
||||||
|
*/
|
||||||
default boolean isGreedy() {
|
default boolean isGreedy() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,30 @@
|
||||||
package de.kentoj.kencommandapi.api.argument;
|
package de.kentoj.kencommandapi.api.argument;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
|
import de.kentoj.kencommandapi.internal.CommandArgumentImpl;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface CommandArgument<T, S extends CommandContext<T, ?>, V> {
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface CommandArgument<T, V> {
|
||||||
|
|
||||||
|
static <T, V> CommandArgument<T, V> arg(String id, ArgumentType<T, V> type) {
|
||||||
|
return new CommandArgumentImpl<>(id, type);
|
||||||
|
}
|
||||||
|
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
ArgumentType<T, S, V> getType();
|
ArgumentType<T, V> getType();
|
||||||
|
|
||||||
void setDefaultValue(@Nullable V defaultValue);
|
void setDefaultValueProvider(@Nullable Function<T, V> getDefaultValueProvider);
|
||||||
|
|
||||||
@Nullable V getDefaultValue();
|
@Nullable Function<T, V> getDefaultValueProvider();
|
||||||
|
|
||||||
void setSuggestionProvider(@Nullable SuggestionProvider<T, S> suggestionProvider);
|
void setSuggestionProvider(@Nullable SuggestionProvider<T> suggestionProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the explicitly set SuggestionProvider or the default suggestions for the type if unset/null
|
* @return the explicitly set SuggestionProvider or the default suggestions for the type if unset/null
|
||||||
*/
|
*/
|
||||||
@NotNull SuggestionProvider<T, S> getSuggestionProvider();
|
@NotNull SuggestionProvider<T> getSuggestionProvider();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.argument;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public interface SuggestionProvider<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
CompletableFuture<Set<String>> suggest(S context);
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.argument.suggestion;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public class NoSuggestionProvider<T, S extends CommandContext<T, ?>> implements SuggestionProvider<T, S> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Set<String>> suggest(S ctx) {
|
|
||||||
return CompletableFuture.completedFuture(Collections.emptySet());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package de.kentoj.kencommandapi.api.argument.types;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
||||||
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
|
import de.kentoj.kencommandapi.api.suggestion.NoSuggestionProvider;
|
||||||
|
|
||||||
|
public class IntegerArgumentType<T> implements ArgumentType<T, Integer> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer parseInput(String string) {
|
||||||
|
return Integer.parseInt(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuggestionProvider<T> defaultSuggestionProvider() {
|
||||||
|
return new NoSuggestionProvider<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
package de.kentoj.kencommandapi.api.types;
|
package de.kentoj.kencommandapi.api.argument.types;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
import de.kentoj.kencommandapi.api.argument.suggestion.NoSuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.NoSuggestionProvider;
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class StringArgumentType<T, S extends CommandContext<T, ?>> implements ArgumentType<T, S, String> {
|
public class StringArgumentType<T> implements ArgumentType<T, String> {
|
||||||
|
|
||||||
private final boolean isGreedy;
|
private final boolean isGreedy;
|
||||||
|
|
||||||
|
|
@ -22,7 +20,7 @@ public class StringArgumentType<T, S extends CommandContext<T, ?>> implements Ar
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SuggestionProvider<T, S> defaultSuggestionProvider() {
|
public SuggestionProvider<T> defaultSuggestionProvider() {
|
||||||
return new NoSuggestionProvider<>();
|
return new NoSuggestionProvider<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package de.kentoj.kencommandapi.api.invocation;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandContext<T> {
|
||||||
|
@Getter
|
||||||
|
private final T sender;
|
||||||
|
@Getter
|
||||||
|
private final Map<String, ParsedArgument<T, ?>> parsedArguments;
|
||||||
|
|
||||||
|
public <V> ParsedArgument<T, V> getParsedArgument(String name) {
|
||||||
|
try {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (ParsedArgument<T, V>) parsedArguments.get(name);
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new RuntimeException("requested argument with wrong type", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <V> V getArg(String name) {
|
||||||
|
return (V) getParsedArgument(name).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V> V getArg(CommandArgument<T, V> arg) {
|
||||||
|
return getArg(arg.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V> ParsedArgument<T, V> getParsedArgument(CommandArgument<T, V> arg) {
|
||||||
|
return getParsedArgument(arg.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package de.kentoj.kencommandapi.api.invocation;
|
||||||
|
|
||||||
|
public interface CommandExecutor<T> {
|
||||||
|
|
||||||
|
Result execute(CommandContext<T> ctx);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package de.kentoj.kencommandapi.api.invocation;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
|
||||||
|
public interface ParsedArgument<T, V> {
|
||||||
|
|
||||||
|
V getValue();
|
||||||
|
|
||||||
|
CommandArgument<T, V> getArgument();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package de.kentoj.kencommandapi.api.invocation;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class Result {
|
||||||
|
|
||||||
|
public static Result success() {
|
||||||
|
return new Result(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result error(String error) {
|
||||||
|
return new Result(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final @Nullable String error;
|
||||||
|
|
||||||
|
public boolean isError() {
|
||||||
|
return error != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.nodes;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface ArgumentNode<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
<V> void addArgument(CommandArgument<T, S, V> argument);
|
|
||||||
|
|
||||||
List<CommandArgument<T, S, ?>> getArguments();
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.nodes;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param <S> type of command context
|
|
||||||
*/
|
|
||||||
public interface CommandNode<T, S extends CommandContext<T, ?>> extends ArgumentNode<T, S>, LiteralNode<T, S> {
|
|
||||||
|
|
||||||
@NotNull String[] getNames();
|
|
||||||
|
|
||||||
void setExecutor(@Nullable CommandExecutor<T, S> executor);
|
|
||||||
|
|
||||||
@Nullable CommandExecutor<T, S> getExecutor();
|
|
||||||
|
|
||||||
void setDescription(@Nullable String description);
|
|
||||||
|
|
||||||
@Nullable String getDescription();
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.nodes;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface LiteralNode<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
void addLiteral(@NotNull CommandNode<T, S> commandNode);
|
|
||||||
|
|
||||||
@Nullable CommandNode<T, S> getLiteral(@NotNull String name);
|
|
||||||
|
|
||||||
@NotNull Set<CommandNode<T, S>> getLiterals();
|
|
||||||
|
|
||||||
@Nullable String getPermission();
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.processing;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
|
|
||||||
public interface CommandContext<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
T getSender();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Object that is parsed from the raw argument
|
|
||||||
* @throws RuntimeException if no value given and no default value supplied
|
|
||||||
*/
|
|
||||||
<V> ParsedArgument<T, S, V> getParsedArgument(String name);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default <V> V getArg(String name) {
|
|
||||||
return (V) getParsedArgument(name).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
default <V> V getArg(CommandArgument<T, S, V> arg) {
|
|
||||||
return getArg(arg.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
default <V> ParsedArgument<T, S, V> getParsedArgument(CommandArgument<T, S, V> arg) {
|
|
||||||
return getParsedArgument(arg.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.processing;
|
|
||||||
|
|
||||||
public class CommandException extends RuntimeException {
|
|
||||||
public CommandException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.processing;
|
|
||||||
|
|
||||||
public interface CommandExecutor<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
void execute(S ctx);
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.processing;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
|
|
||||||
public interface ParsedArgument<T, S extends CommandContext<T, ?>, V> {
|
|
||||||
|
|
||||||
V getValue();
|
|
||||||
|
|
||||||
CommandArgument<T, S, V> getArgument();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package de.kentoj.kencommandapi.api.suggestion;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class NoSuggestionProvider<T> implements SuggestionProvider<T> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Set<String>> suggest(CommandContext<T> __) {
|
||||||
|
return CompletableFuture.completedFuture(Collections.emptySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package de.kentoj.kencommandapi.api.suggestion;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public interface SuggestionProvider<T> {
|
||||||
|
|
||||||
|
CompletableFuture<Set<String>> suggest(CommandContext<T> context);
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.api.types;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.suggestion.NoSuggestionProvider;
|
|
||||||
|
|
||||||
public class IntegerArgumentType<T, S extends CommandContext<T, ?>> implements ArgumentType<T, S, Integer> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer parseInput(String string) {
|
|
||||||
return Integer.parseInt(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SuggestionProvider<T, S> defaultSuggestionProvider() {
|
|
||||||
return new NoSuggestionProvider<>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.impl;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.KenCommandApi;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.impl.processing.ParsedArgumentImpl;
|
|
||||||
import de.kentoj.kencommandapi.impl.structure.CommandArgumentImpl;
|
|
||||||
import de.kentoj.kencommandapi.impl.structure.CommandNodeImpl;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public abstract class AbstractKenCommandApi<T, S extends CommandContext<T, ?>> implements KenCommandApi<T, S> {
|
|
||||||
|
|
||||||
public abstract S createContext(T sender, Map<String, ParsedArgument<T, S, ?>> parsedArguments);
|
|
||||||
|
|
||||||
public abstract void sendErrorMessage(T t, CommandException exception);
|
|
||||||
|
|
||||||
public abstract boolean hasPermission(T t, String permission);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandNode<T, S> createNode(String... name) {
|
|
||||||
return new CommandNodeImpl<>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <V> CommandArgument<T, S, V> createArgument(String id, ArgumentType<T, S, V> type) {
|
|
||||||
return new CommandArgumentImpl<>(id, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invoke(CommandNode<T, S> node, T sender, String[] args) {
|
|
||||||
var iter = Arrays.stream(args).iterator();
|
|
||||||
|
|
||||||
try {
|
|
||||||
var executableLiteral = processLiterals(sender, node, iter);
|
|
||||||
var parsedArguments = parseArguments(executableLiteral, iter);
|
|
||||||
assert executableLiteral.getExecutor() != null;
|
|
||||||
executableLiteral.getExecutor().execute(createContext(sender, parsedArguments));
|
|
||||||
} catch (CommandException ex) {
|
|
||||||
sendErrorMessage(sender, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CommandNode<T, S> processLiterals(T sender, CommandNode<T, S> commandNode, Iterator<String> iter) {
|
|
||||||
if (!iter.hasNext()) {
|
|
||||||
// literals/arguments are optional if the node itself is executable
|
|
||||||
if (commandNode.getExecutor() == null) throw new CommandException("no literal given but required");
|
|
||||||
return commandNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandNode.getLiterals().isEmpty()) {
|
|
||||||
return commandNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
final var arg = iter.next();
|
|
||||||
final var literal = commandNode.getLiteral(arg);
|
|
||||||
if (literal == null) {
|
|
||||||
throw new CommandException("Invalid literal: " + arg);
|
|
||||||
}
|
|
||||||
if (literal.getPermission() != null && !hasPermission(sender, literal.getPermission())) {
|
|
||||||
throw new CommandException("No permission");
|
|
||||||
}
|
|
||||||
return processLiterals(sender, literal, iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, ParsedArgument<T, S, ?>> parseArguments(CommandNode<T, S> commandNode, Iterator<String> iter) {
|
|
||||||
Map<String, ParsedArgument<T, S, ?>> parsedArguments = new HashMap<>();
|
|
||||||
for (var argument : commandNode.getArguments()) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
var arg = ((CommandArgument<T, S, Object>) argument);
|
|
||||||
|
|
||||||
if (!iter.hasNext()) {
|
|
||||||
var defaultValue = arg.getDefaultValue();
|
|
||||||
if (defaultValue == null) throw new CommandException("no argument given but required");
|
|
||||||
parsedArguments.put(arg.getId(), new ParsedArgumentImpl<>(defaultValue, arg));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rawArgument = getRawArgument(arg, iter);
|
|
||||||
var parsedArg = arg.getType().parseInput(rawArgument);
|
|
||||||
parsedArguments.put(arg.getId(), new ParsedArgumentImpl<>(parsedArg, arg));
|
|
||||||
}
|
|
||||||
return parsedArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getRawArgument(CommandArgument<T, S, Object> arg, Iterator<String> iter) {
|
|
||||||
var rawArgument = "";
|
|
||||||
if (arg.getType().isGreedy()) {
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
//noinspection StringConcatenationInLoop
|
|
||||||
rawArgument += iter.next();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rawArgument = iter.next();
|
|
||||||
}
|
|
||||||
return rawArgument;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.impl.processing;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class CommandContextImpl<T, S extends CommandContext<T, ?>> implements CommandContext<T, S> {
|
|
||||||
@Getter
|
|
||||||
private final T sender;
|
|
||||||
@Getter
|
|
||||||
private final Map<String, ParsedArgument<T, S, ?>> parsedArguments;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <V> ParsedArgument<T, S, V> getParsedArgument(String name) {
|
|
||||||
try {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (ParsedArgument<T, S, V>) parsedArguments.get(name);
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
throw new RuntimeException("requested argument with wrong type", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.impl.processing;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
public class ParsedArgumentImpl<T, S extends CommandContext<T, ?>, V> implements ParsedArgument<T, S, V> {
|
|
||||||
V value;
|
|
||||||
CommandArgument<T, S, V> argument;
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.impl.processing;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TabCompleter<T, S extends CommandContext<T, ?>> {
|
|
||||||
|
|
||||||
private List<String> tabComplete(CommandNode<T, S> node, String[] args) {
|
|
||||||
var lastNode = node;
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
var tmp = node.getLiteral(args[i]);
|
|
||||||
if (tmp == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastNode = tmp;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.getLiterals().stream().map(CommandNode::getNames).flatMap(Arrays::stream).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.impl.structure;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class CommandArgumentImpl<T, S extends CommandContext<T, ?>, V> implements CommandArgument<T, S, V> {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final String id;
|
|
||||||
@Getter
|
|
||||||
private final ArgumentType<T, S, V> type;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private @Nullable V defaultValue;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private @Nullable SuggestionProvider<T, S> suggestionProvider;
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
package de.kentoj.kencommandapi.impl.structure;
|
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class CommandNodeImpl<T, S extends CommandContext<T, ?>> implements CommandNode<T, S> {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final String[] names;
|
|
||||||
@Getter
|
|
||||||
private final Set<CommandNode<T, S>> literals = new HashSet<>();
|
|
||||||
@Getter
|
|
||||||
private final List<CommandArgument<T, S, ?>> arguments = new ArrayList<>();
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private @Nullable CommandExecutor<T, S> executor;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private @Nullable String permission = null;
|
|
||||||
|
|
||||||
public CommandNodeImpl(String[] names) {
|
|
||||||
if (names.length == 0) throw new IllegalArgumentException("at least one name is required");
|
|
||||||
this.names = names;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addLiteral(@NotNull CommandNode<T, S> commandNode) {
|
|
||||||
for (String name : commandNode.getNames()) {
|
|
||||||
if (getLiteral(name) != null) throw new IllegalArgumentException("literal with same name is already added");
|
|
||||||
}
|
|
||||||
literals.add(commandNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandNode<T, S> getLiteral(@NotNull String name) {
|
|
||||||
for (var literal : literals) {
|
|
||||||
for (String literalName : literal.getNames()) {
|
|
||||||
if (literalName.equalsIgnoreCase(name)) return literal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <V> void addArgument(CommandArgument<T, S, V> argument) {
|
|
||||||
if (arguments.stream()
|
|
||||||
.anyMatch(arg -> arg.getId().equals(argument.getId()))
|
|
||||||
) throw new IllegalArgumentException("argument with same identifier is already added");
|
|
||||||
if (!arguments.isEmpty() && arguments.getLast().getType().isGreedy())
|
|
||||||
throw new IllegalStateException("can't append argument to a node, whose last argument type is greedy: "
|
|
||||||
+ arguments.getLast().getType().getClass().getCanonicalName());
|
|
||||||
|
|
||||||
arguments.add(argument);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package de.kentoj.kencommandapi.internal;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandArgumentImpl<T, V> implements CommandArgument<T, V> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final String id;
|
||||||
|
@Getter
|
||||||
|
private final ArgumentType<T, V> type;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private @Nullable Function<T, V> defaultValueProvider;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private @Nullable SuggestionProvider<T> suggestionProvider;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package de.kentoj.kencommandapi.internal;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class CommandNodeImpl<T> implements CommandNode<T> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final String[] names;
|
||||||
|
@Getter
|
||||||
|
private final Set<CommandNode<T>> literals = new HashSet<>();
|
||||||
|
@Getter
|
||||||
|
private final List<CommandArgument<T, ?>> arguments = new ArrayList<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private @Nullable CommandExecutor<T> executor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private @Nullable String permission = null;
|
||||||
|
|
||||||
|
public CommandNodeImpl(String[] names) {
|
||||||
|
if (names.length == 0) throw new IllegalArgumentException("at least one name is required");
|
||||||
|
this.names = names;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLiteral(@NotNull CommandNode<T> commandNode) {
|
||||||
|
if (isGreedy()) throw new IllegalStateException("can't add literal to a node with a greedy argument");
|
||||||
|
for (String name : commandNode.getNames())
|
||||||
|
if (getLiteral(name) != null)
|
||||||
|
throw new IllegalArgumentException("literal with same name is already exists");
|
||||||
|
literals.add(commandNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandNode<T> getLiteral(@NotNull String name) {
|
||||||
|
for (var literal : literals)
|
||||||
|
for (String literalName : literal.getNames())
|
||||||
|
if (literalName.equalsIgnoreCase(name)) return literal;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <V> void addArgument(CommandArgument<T, V> argument) {
|
||||||
|
if (isGreedy()) throw new IllegalStateException("can't add literal to a node with a greedy argument");
|
||||||
|
if (arguments.stream().anyMatch(arg -> arg.getId().equals(argument.getId())))
|
||||||
|
throw new IllegalArgumentException("argument with same identifier is already added");
|
||||||
|
arguments.add(argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isGreedy() {
|
||||||
|
var arg = arguments.getLast();
|
||||||
|
return arg != null && arg.getType().isGreedy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package de.kentoj.kencommandapi.internal;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
public class ParsedArgumentImpl<T, V> implements ParsedArgument<T, V> {
|
||||||
|
V value;
|
||||||
|
CommandArgument<T, V> argument;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package de.kentoj.kencommandapi.internal.parser;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||||
|
import de.kentoj.kencommandapi.internal.ParsedArgumentImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandParser<T> {
|
||||||
|
|
||||||
|
private final PermissionChecker<T> hasPermissionMethod;
|
||||||
|
|
||||||
|
public ParseResult<T> parseLiteral(CommandNode<T> rootNode, T sender, String[] args) {
|
||||||
|
var cur = rootNode;
|
||||||
|
final Iterator<String> argStrIter = Arrays.stream(args).iterator();
|
||||||
|
final Map<String, ParsedArgument<T, ?>> parsedArguments = new HashMap<>();
|
||||||
|
|
||||||
|
while (argStrIter.hasNext()) {
|
||||||
|
for (var nodeArg : cur.getArguments()) {
|
||||||
|
ParsedArgument<T, Object> parsed;
|
||||||
|
try {
|
||||||
|
parsed = parseArgument(argStrIter, sender, nodeArg);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
return new ParseResult.IllegalArgument<>(cur, ex.getMessage());
|
||||||
|
}
|
||||||
|
if (parsed == null) return new ParseResult.IncompleteArgument<>(cur, nodeArg);
|
||||||
|
parsedArguments.put(nodeArg.getId(), parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argStrIter.hasNext()) {
|
||||||
|
if (cur.getExecutor() == null)
|
||||||
|
return new ParseResult.IncompleteCommand<>(cur);
|
||||||
|
return new ParseResult.Success<>(cur, parsedArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
var argStr = argStrIter.next();
|
||||||
|
var nextNode = cur.getLiteral(argStr);
|
||||||
|
if (nextNode == null)
|
||||||
|
return new ParseResult.UnknownLiteral<>(cur, argStr);
|
||||||
|
if (nextNode.getPermission() != null && !hasPermissionMethod.hasPermission(sender, nextNode.getPermission()))
|
||||||
|
return new ParseResult.NoPermission<>(cur, argStr);
|
||||||
|
cur = nextNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("code reached unexpected line");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private ParsedArgument<T, Object> parseArgument(Iterator<String> args, T sender, CommandArgument<T, ?> nodeArg) {
|
||||||
|
Object value;
|
||||||
|
|
||||||
|
if (args.hasNext()) {
|
||||||
|
var argStr = getRawArgument(args, nodeArg);
|
||||||
|
value = nodeArg.getType().parseInput(argStr);
|
||||||
|
} else {
|
||||||
|
if (nodeArg.getDefaultValueProvider() == null)
|
||||||
|
return null;
|
||||||
|
value = nodeArg.getDefaultValueProvider().apply(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ParsedArgumentImpl<>(value, (CommandArgument<T, Object>) nodeArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRawArgument(Iterator<String> args, CommandArgument<T, ?> arg) {
|
||||||
|
StringBuilder rawArgument = new StringBuilder();
|
||||||
|
|
||||||
|
if (arg.getType().isGreedy()) {
|
||||||
|
while (args.hasNext()) {
|
||||||
|
rawArgument.append(args.next());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rawArgument = new StringBuilder(args.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawArgument.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
package de.kentoj.kencommandapi.internal.parser;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
|
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument, ParseResult.IncompleteArgument,
|
||||||
|
ParseResult.IncompleteCommand, ParseResult.NoPermission, ParseResult.Success, ParseResult.UnknownLiteral {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return last successfully literal
|
||||||
|
*/
|
||||||
|
public abstract CommandNode<T> getLiteral();
|
||||||
|
|
||||||
|
public abstract String getMessage();
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static final class IncompleteArgument<T> extends ParseResult<T> {
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<T> literal;
|
||||||
|
private final CommandArgument<T, ?> argument;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "Missing value for argument: " + argument.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static final class UnknownLiteral<T> extends ParseResult<T> {
|
||||||
|
private final CommandNode<T> previousLiteral;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "Unknown literal: " + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandNode<T> getLiteral() {
|
||||||
|
return previousLiteral;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static final class IncompleteCommand<T> extends ParseResult<T> {
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<T> literal;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "Incomplete command";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static final class Success<T> extends ParseResult<T> {
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<T> literal;
|
||||||
|
@Getter
|
||||||
|
private final Map<String, ParsedArgument<T, ?>> parsedArguments;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static final class NoPermission<T> extends ParseResult<T> {
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<T> literal;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "Unknown literal: " + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public static final class IllegalArgument<T> extends ParseResult<T> {
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<T> literal;
|
||||||
|
@Getter
|
||||||
|
private final String message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package de.kentoj.kencommandapi.internal.parser;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface PermissionChecker<T> {
|
||||||
|
boolean hasPermission(T sender, String permission);
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
plugins {
|
plugins {
|
||||||
id("java")
|
id("java")
|
||||||
id("java-library")
|
id("maven-publish")
|
||||||
|
id("de.kentoj.scrow.scrow-repository")
|
||||||
|
id("de.kentoj.scrow.base-dependencies")
|
||||||
|
id("de.kentoj.scrow.java-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "de.kentoj.scrow"
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
|
||||||
maven {
|
maven {
|
||||||
name = "papermc"
|
name = "papermc"
|
||||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||||
|
|
@ -20,4 +19,15 @@ dependencies {
|
||||||
compileOnly("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")
|
compileOnly("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")
|
||||||
|
|
||||||
api(project(":kencommandapi-core"))
|
api(project(":kencommandapi-core"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("KenCommandAPI") {
|
||||||
|
groupId = rootProject.group.toString()
|
||||||
|
version = rootProject.version.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
from(components["java"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package de.kentoj.kencommandapi;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
|
import de.kentoj.kencommandapi.internal.parser.CommandParser;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandAPI {
|
||||||
|
|
||||||
|
private final ProxyServer server;
|
||||||
|
private final CommandParser<CommandSource> commandParser = new CommandParser<>(CommandSource::hasPermission);
|
||||||
|
|
||||||
|
public void register(CommandNode<CommandSource> rootNode) {
|
||||||
|
var cm = server.getCommandManager();
|
||||||
|
var meta = cm.metaBuilder(rootNode.getNames()[0])
|
||||||
|
.aliases(Arrays.copyOfRange(rootNode.getNames(), 1, rootNode.getNames().length - 1))
|
||||||
|
.build();
|
||||||
|
cm.register(meta, new VelocityCommand(commandParser, rootNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,22 +2,47 @@ package de.kentoj.kencommandapi;
|
||||||
|
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
import com.velocitypowered.api.command.SimpleCommand;
|
import com.velocitypowered.api.command.SimpleCommand;
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
import de.kentoj.kencommandapi.api.CommandNode;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||||
|
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||||
|
import de.kentoj.kencommandapi.internal.parser.CommandParser;
|
||||||
|
import de.kentoj.kencommandapi.internal.parser.ParseResult;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class VelocityCommand implements SimpleCommand {
|
public class VelocityCommand implements SimpleCommand {
|
||||||
|
|
||||||
private final VelocityKenCommandApi commandApi;
|
private final CommandParser<CommandSource> commandParser;
|
||||||
private final CommandNode<CommandSource, VelocityCommandContext> rootNode;
|
private final CommandNode<CommandSource> rootNode;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Invocation ctx) {
|
public void execute(Invocation invocation) {
|
||||||
commandApi.invoke(rootNode, ctx.source(), ctx.arguments());
|
var parseResult = commandParser.parseLiteral(rootNode, invocation.source(), invocation.arguments());
|
||||||
|
if (parseResult instanceof ParseResult.Success<CommandSource>) {
|
||||||
|
var ctx = new CommandContext<>(invocation.source(), ((ParseResult.Success<CommandSource>) parseResult).getParsedArguments());
|
||||||
|
assert parseResult.getLiteral().getExecutor() != null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var result = parseResult.getLiteral().getExecutor().execute(ctx);
|
||||||
|
if (result.getError() != null)
|
||||||
|
invocation.source().sendMessage(Component.text(result.getError()).color(NamedTextColor.RED));
|
||||||
|
} catch (Exception e) {
|
||||||
|
invocation.source().sendMessage(Component.text("ERROR ")
|
||||||
|
.append(Component.text(e.getMessage()))
|
||||||
|
.color(NamedTextColor.DARK_RED)
|
||||||
|
.decorate(TextDecoration.BOLD));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
invocation.source().sendMessage(Component.text(parseResult.getMessage()).color(NamedTextColor.RED));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPermission(Invocation ctx) {
|
public boolean hasPermission(Invocation ctx) {
|
||||||
return commandApi.hasPermission(ctx.source(), rootNode.getPermission());
|
if (rootNode.getPermission() == null) return true;
|
||||||
|
return ctx.source().hasPermission(rootNode.getPermission());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package de.kentoj.kencommandapi;
|
|
||||||
|
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
|
||||||
import com.velocitypowered.api.proxy.Player;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.impl.processing.CommandContextImpl;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class VelocityCommandContext extends CommandContextImpl<CommandSource, VelocityCommandContext> {
|
|
||||||
|
|
||||||
VelocityCommandContext(
|
|
||||||
CommandSource sender,
|
|
||||||
Map<String, ParsedArgument<CommandSource, VelocityCommandContext, ?>> parsedArguments
|
|
||||||
) {
|
|
||||||
super(sender, parsedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Player getPlayerSender() {
|
|
||||||
return (Player) getSender();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
package de.kentoj.kencommandapi;
|
|
||||||
|
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
|
||||||
import de.kentoj.kencommandapi.api.nodes.CommandNode;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
|
|
||||||
import de.kentoj.kencommandapi.impl.AbstractKenCommandApi;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class VelocityKenCommandApi extends AbstractKenCommandApi<CommandSource, VelocityCommandContext> {
|
|
||||||
|
|
||||||
private final ProxyServer server;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VelocityCommandContext createContext(CommandSource sender, Map<String, ParsedArgument<CommandSource, VelocityCommandContext, ?>> parsedArguments) {
|
|
||||||
return new VelocityCommandContext(sender, parsedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendErrorMessage(CommandSource sender, CommandException ex) {
|
|
||||||
var cause = (ex.getCause() != null) ? ": " + ex.getCause().getMessage() : "";
|
|
||||||
sender.sendMessage(Component.text(ex.getMessage() + cause).color(NamedTextColor.RED));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(CommandSource commandSource, String permission) {
|
|
||||||
return commandSource.hasPermission(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(CommandNode<CommandSource, VelocityCommandContext> rootNode) {
|
|
||||||
var cm = server.getCommandManager();
|
|
||||||
var meta = cm.metaBuilder(rootNode.getNames()[0])
|
|
||||||
.aliases(Arrays.copyOfRange(rootNode.getNames(), 1, rootNode.getNames().length - 1))
|
|
||||||
.build();
|
|
||||||
cm.register(meta, new VelocityCommand(this, rootNode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,8 +3,8 @@ package de.kentoj.kencommandapi.suggestionprovider;
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import de.kentoj.kencommandapi.VelocityCommandContext;
|
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -12,12 +12,12 @@ import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSource, VelocityCommandContext> {
|
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSource> {
|
||||||
|
|
||||||
private final ProxyServer proxyServer;
|
private final ProxyServer proxyServer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Set<String>> suggest(VelocityCommandContext context) {
|
public CompletableFuture<Set<String>> suggest(CommandContext<CommandSource> context) {
|
||||||
var list = proxyServer.getAllPlayers().stream()
|
var list = proxyServer.getAllPlayers().stream()
|
||||||
.map(Player::getUsername)
|
.map(Player::getUsername)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
|
||||||
|
|
@ -3,27 +3,25 @@ package de.kentoj.kencommandapi.type;
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import de.kentoj.kencommandapi.VelocityCommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
import de.kentoj.kencommandapi.api.argument.ArgumentType;
|
||||||
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
|
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandException;
|
|
||||||
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
|
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PlayerArgumentType implements ArgumentType<CommandSource, VelocityCommandContext, Player> {
|
public class PlayerArgumentType implements ArgumentType<CommandSource, Player> {
|
||||||
|
|
||||||
private final ProxyServer server;
|
private final ProxyServer server;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Player parseInput(String string) {
|
public Player parseInput(String string) {
|
||||||
var player = server.getPlayer(string).orElse(null);
|
var player = server.getPlayer(string).orElse(null);
|
||||||
if (player == null) throw new CommandException("Player not online -- " + string);
|
if (player == null) throw new IllegalArgumentException("Player not online -- " + string);
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SuggestionProvider<CommandSource, VelocityCommandContext> defaultSuggestionProvider() {
|
public SuggestionProvider<CommandSource> defaultSuggestionProvider() {
|
||||||
return new PlayerSuggestionProvider(server);
|
return new PlayerSuggestionProvider(server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
rootProject.name = "KenCommandAPI"
|
rootProject.name = "KenCommandAPI"
|
||||||
|
|
||||||
|
includeBuild("../build-logic")
|
||||||
include("kencommandapi-core")
|
include("kencommandapi-core")
|
||||||
include("kencommandapi-bukkit")
|
include("kencommandapi-bukkit")
|
||||||
include("kencommandapi-velocity")
|
include("kencommandapi-velocity")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue