This commit is contained in:
kento2 2026-06-02 23:48:07 +02:00
parent c2aec2842a
commit 5cec83b992
34 changed files with 269 additions and 58 deletions

1
.idea/gradle.xml generated
View file

@ -11,6 +11,7 @@
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/kencommandapi-bukkit" />
<option value="$PROJECT_DIR$/kencommandapi-core" />
<option value="$PROJECT_DIR$/kencommandapi-velocity" />
</set>
</option>
</GradleProjectSettings>

View file

@ -38,9 +38,6 @@ subprojects {
repositories {
mavenCentral()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
name = "spigotmc-repo"
}
scrowRepo()
}

View file

@ -1,6 +1,3 @@
val scrowToken = providers.gradleProperty("scrowMavenToken")
.orElse(providers.environmentVariable("SCROW_MAVEN_TOKEN")).get()
plugins {
id("java")
id("java-library")
@ -9,6 +6,12 @@ plugins {
group = "de.kentoj"
version = "2.3.0"
repositories {
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
name = "spigotmc-repo"
}
}
dependencies {
api(project(":kencommandapi-core"))
compileOnly("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")

View file

@ -9,7 +9,7 @@ import java.util.Map;
public class BukkitCommandContext extends CommandContextImpl<CommandSender, BukkitCommandContext> {
public BukkitCommandContext(
BukkitCommandContext(
CommandSender sender,
Map<String, ParsedArgument<CommandSender, BukkitCommandContext, ?>> parsedArguments
) {

View file

@ -1,7 +1,7 @@
package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.KenCommandApi;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.kencommandapi.api.nodes.CommandNode;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;

View file

@ -2,7 +2,7 @@ package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.processing.CommandException;
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.kencommandapi.api.nodes.CommandNode;
import de.kentoj.kencommandapi.impl.AbstractKenCommandApi;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;

View file

@ -0,0 +1,21 @@
package de.kentoj.kencommandapi.suggestionprovider;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSender, BukkitCommandContext> {
@Override
public CompletableFuture<Set<String>> suggest(BukkitCommandContext context) {
var list = Bukkit.getOnlinePlayers().stream()
.map(Player::getName)
.collect(Collectors.toSet());
return CompletableFuture.completedFuture(list);
}
}

View file

@ -2,9 +2,10 @@ package de.kentoj.kencommandapi.type;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.processing.CommandException;
import de.kentoj.kencommandapi.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.structure.argument.suggestion.NoSuggestionProvider;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.argument.suggestion.NoSuggestionProvider;
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -12,7 +13,6 @@ import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import java.util.Set;
import java.util.UUID;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ -38,6 +38,6 @@ public class OfflinePlayerArgumentType implements ArgumentType<CommandSender, Bu
@Override
public SuggestionProvider<CommandSender, BukkitCommandContext> defaultSuggestionProvider() {
return new NoSuggestionProvider<>();
return new PlayerSuggestionProvider();
}
}

View file

@ -2,9 +2,10 @@ package de.kentoj.kencommandapi.type;
import de.kentoj.kencommandapi.BukkitCommandContext;
import de.kentoj.kencommandapi.api.processing.CommandException;
import de.kentoj.kencommandapi.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.structure.argument.suggestion.NoSuggestionProvider;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.argument.suggestion.NoSuggestionProvider;
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -13,6 +14,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PlayerArgumentType implements ArgumentType<CommandSender, BukkitCommandContext, Player> {
@ -29,6 +31,6 @@ public class PlayerArgumentType implements ArgumentType<CommandSender, BukkitCom
@Override
public SuggestionProvider<CommandSender, BukkitCommandContext> defaultSuggestionProvider() {
return new NoSuggestionProvider<>();
return new PlayerSuggestionProvider();
}
}

View file

@ -2,7 +2,7 @@ package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.processing.CommandException;
import de.kentoj.kencommandapi.api.processing.ParsedArgument;
import de.kentoj.kencommandapi.api.structure.argument.types.IntegerArgumentType;
import de.kentoj.kencommandapi.api.types.IntegerArgumentType;
import de.kentoj.kencommandapi.impl.AbstractKenCommandApi;
import de.kentoj.kencommandapi.impl.processing.CommandContextImpl;

View file

@ -1,9 +1,9 @@
package de.kentoj.kencommandapi.api;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
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, ?>> {

View file

@ -1,4 +1,4 @@
package de.kentoj.kencommandapi.api.structure.argument;
package de.kentoj.kencommandapi.api.argument;
import de.kentoj.kencommandapi.api.processing.CommandContext;
@ -7,4 +7,8 @@ public interface ArgumentType<T, S extends CommandContext<T, ?>, V> {
V parseInput(String string);
SuggestionProvider<T, S> defaultSuggestionProvider();
default boolean isGreedy() {
return false;
}
}

View file

@ -1,4 +1,4 @@
package de.kentoj.kencommandapi.api.structure.argument;
package de.kentoj.kencommandapi.api.argument;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import org.jetbrains.annotations.NotNull;

View file

@ -1,4 +1,4 @@
package de.kentoj.kencommandapi.api.structure.argument;
package de.kentoj.kencommandapi.api.argument;
import de.kentoj.kencommandapi.api.processing.CommandContext;

View file

@ -1,7 +1,7 @@
package de.kentoj.kencommandapi.api.structure.argument.suggestion;
package de.kentoj.kencommandapi.api.argument.suggestion;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import java.util.Collections;
import java.util.Set;

View file

@ -1,7 +1,7 @@
package de.kentoj.kencommandapi.api.structure.node;
package de.kentoj.kencommandapi.api.nodes;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import java.util.Set;

View file

@ -1,4 +1,4 @@
package de.kentoj.kencommandapi.api.structure.node;
package de.kentoj.kencommandapi.api.nodes;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.processing.CommandExecutor;

View file

@ -1,4 +1,4 @@
package de.kentoj.kencommandapi.api.structure.node;
package de.kentoj.kencommandapi.api.nodes;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import org.jetbrains.annotations.NotNull;

View file

@ -1,6 +1,6 @@
package de.kentoj.kencommandapi.api.processing;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
public interface CommandContext<T, S extends CommandContext<T, ?>> {

View file

@ -1,6 +1,6 @@
package de.kentoj.kencommandapi.api.processing;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
public interface ParsedArgument<T, S extends CommandContext<T, ?>, V> {

View file

@ -1,9 +1,9 @@
package de.kentoj.kencommandapi.api.structure.argument.types;
package de.kentoj.kencommandapi.api.types;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.structure.argument.suggestion.NoSuggestionProvider;
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> {

View file

@ -1,10 +1,9 @@
package de.kentoj.kencommandapi.api.structure.argument.types;
package de.kentoj.kencommandapi.api.types;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.structure.argument.suggestion.NoSuggestionProvider;
import lombok.Getter;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.argument.suggestion.NoSuggestionProvider;
public class StringArgumentType<T, S extends CommandContext<T, ?>> implements ArgumentType<T, S, String> {

View file

@ -4,9 +4,9 @@ import de.kentoj.kencommandapi.api.KenCommandApi;
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.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
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.impl.processing.ParsedArgumentImpl;
import de.kentoj.kencommandapi.impl.structure.CommandArgumentImpl;
import de.kentoj.kencommandapi.impl.structure.CommandNodeImpl;
@ -16,6 +16,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public abstract class AbstractKenCommandApi<T, S extends CommandContext<T, ?>> implements KenCommandApi<T, S> {
@ -85,9 +86,23 @@ public abstract class AbstractKenCommandApi<T, S extends CommandContext<T, ?>> i
continue;
}
var parsedArg = arg.getType().parseInput(iter.next());
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;
}
}

View file

@ -2,7 +2,7 @@ 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.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import lombok.Value;
@Value

View file

@ -1,7 +1,7 @@
package de.kentoj.kencommandapi.impl.processing;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import de.kentoj.kencommandapi.api.nodes.CommandNode;
import java.util.Arrays;
import java.util.List;

View file

@ -1,9 +1,9 @@
package de.kentoj.kencommandapi.impl.structure;
import de.kentoj.kencommandapi.api.processing.CommandContext;
import de.kentoj.kencommandapi.api.structure.argument.ArgumentType;
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.structure.argument.SuggestionProvider;
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;

View file

@ -1,15 +1,16 @@
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 de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class CommandNodeImpl<T, S extends CommandContext<T, ?>> implements CommandNode<T, S> {
@ -19,7 +20,7 @@ public class CommandNodeImpl<T, S extends CommandContext<T, ?>> implements Comma
@Getter
private final Set<CommandNode<T, S>> literals = new HashSet<>();
@Getter
private final Set<CommandArgument<T, S, ?>> arguments = new HashSet<>();
private final List<CommandArgument<T, S, ?>> arguments = new HashSet<>();
@Getter
@Setter
@ -59,9 +60,10 @@ public class CommandNodeImpl<T, S extends CommandContext<T, ?>> implements Comma
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");
}
) throw new IllegalArgumentException("argument with same identifier is already added");
if (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);
}

View file

@ -0,0 +1,23 @@
plugins {
id("java")
id("java-library")
}
group = "de.kentoj.scrow"
version = ""
repositories {
mavenCentral()
maven {
name = "papermc"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
}
dependencies {
// https://docs.papermc.io/velocity/dev/creating-your-first-plugin/
annotationProcessor("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")
compileOnly("com.velocitypowered:velocity-api:3.5.0-SNAPSHOT")
api(project(":kencommandapi-core"))
}

View file

@ -0,0 +1,23 @@
package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand;
import de.kentoj.kencommandapi.api.nodes.CommandNode;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class VelocityCommand implements SimpleCommand {
private final VelocityKenCommandApi commandApi;
private final CommandNode<CommandSource, VelocityCommandContext> rootNode;
@Override
public void execute(Invocation ctx) {
commandApi.invoke(rootNode, ctx.source(), ctx.arguments());
}
@Override
public boolean hasPermission(Invocation ctx) {
return commandApi.hasPermission(ctx.source(), rootNode.getPermission());
}
}

View file

@ -0,0 +1,22 @@
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();
}
}

View file

@ -0,0 +1,43 @@
package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer;
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 lombok.RequiredArgsConstructor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
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(rootNode.getNames())
.build();
cm.register(meta, new VelocityCommand(this, rootNode));
}
}

View file

@ -0,0 +1,26 @@
package de.kentoj.kencommandapi.suggestionprovider;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.VelocityCommandContext;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import lombok.RequiredArgsConstructor;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSource, VelocityCommandContext> {
private final ProxyServer proxyServer;
@Override
public CompletableFuture<Set<String>> suggest(VelocityCommandContext context) {
var list = proxyServer.getAllPlayers().stream()
.map(Player::getUsername)
.collect(Collectors.toSet());
return CompletableFuture.completedFuture(list);
}
}

View file

@ -0,0 +1,29 @@
package de.kentoj.kencommandapi.type;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.VelocityCommandContext;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.argument.SuggestionProvider;
import de.kentoj.kencommandapi.api.processing.CommandException;
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class PlayerArgumentType implements ArgumentType<CommandSource, VelocityCommandContext, Player> {
private final ProxyServer server;
@Override
public Player parseInput(String string) {
var player = server.getPlayer(string).orElse(null);
if (player == null) throw new CommandException("Player not online -- " + string);
return player;
}
@Override
public SuggestionProvider<CommandSource, VelocityCommandContext> defaultSuggestionProvider() {
return new PlayerSuggestionProvider(server);
}
}

View file

@ -2,3 +2,4 @@ rootProject.name = "KenCommandAPI"
include("kencommandapi-core")
include("kencommandapi-bukkit")
include("kencommandapi-velocity")