From fc431bf8dfb65f341f65a3c498883579d43450d0 Mon Sep 17 00:00:00 2001 From: kento2 Date: Wed, 15 Apr 2026 10:24:26 +0200 Subject: [PATCH] . --- .../java/de/kencommand/KenCommandAPI.java | 22 ------- .../java/de/kencommand/api/KenCommandApi.java | 17 +++++ .../api/parsing/ParsedArgument.java | 11 ---- .../api/processing/CommandContext.java | 25 ++----- .../api/processing/CommandExecutor.java | 4 +- .../api/processing/ParsedArgument.java | 10 +++ .../api/structure/argument/ArgumentType.java | 4 +- .../structure/argument/CommandArgument.java | 6 +- .../argument/SuggestionProvider.java | 4 +- .../api/structure/node/ArgumentNode.java | 7 +- .../api/structure/node/CommandNode.java | 8 +-- .../api/structure/node/LiteralNode.java | 10 +-- .../de/kencommand/impl/KenCommandApiImpl.java | 66 +++++++++++++++++++ .../impl/parsing/CommandNodeParser.java | 29 -------- .../impl/processing/CommandContextImpl.java | 26 ++++++++ .../impl/processing/ParsedArgumentImpl.java | 11 ++++ .../impl/structure/node/CommandNodeImpl.java | 14 ++-- 17 files changed, 160 insertions(+), 114 deletions(-) delete mode 100644 src/main/java/de/kencommand/KenCommandAPI.java create mode 100644 src/main/java/de/kencommand/api/KenCommandApi.java delete mode 100644 src/main/java/de/kencommand/api/parsing/ParsedArgument.java create mode 100644 src/main/java/de/kencommand/api/processing/ParsedArgument.java create mode 100644 src/main/java/de/kencommand/impl/KenCommandApiImpl.java delete mode 100644 src/main/java/de/kencommand/impl/parsing/CommandNodeParser.java create mode 100644 src/main/java/de/kencommand/impl/processing/CommandContextImpl.java create mode 100644 src/main/java/de/kencommand/impl/processing/ParsedArgumentImpl.java diff --git a/src/main/java/de/kencommand/KenCommandAPI.java b/src/main/java/de/kencommand/KenCommandAPI.java deleted file mode 100644 index eec986e..0000000 --- a/src/main/java/de/kencommand/KenCommandAPI.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.kencommand; - -import de.kencommand.api.processing.CommandContext; -import de.kencommand.api.structure.argument.ArgumentType; -import de.kencommand.api.structure.argument.CommandArgument; -import de.kencommand.api.structure.node.CommandNode; -import de.kencommand.impl.structure.argument.CommandArgumentImpl; -import de.kencommand.impl.structure.node.CommandNodeImpl; - -public class KenCommandAPI { - - private KenCommandAPI() { - } - - public static > CommandNode createCommandNode(String[] names) { - return new CommandNodeImpl(names); - } - - public static , V> CommandArgument createArgument(String id, ArgumentType type) { - return new CommandArgumentImpl<>(id, type); - } -} diff --git a/src/main/java/de/kencommand/api/KenCommandApi.java b/src/main/java/de/kencommand/api/KenCommandApi.java new file mode 100644 index 0000000..bdea91a --- /dev/null +++ b/src/main/java/de/kencommand/api/KenCommandApi.java @@ -0,0 +1,17 @@ +package de.kencommand.api; + +import de.kencommand.api.processing.CommandExecutor; +import de.kencommand.api.processing.ParsedArgument; +import de.kencommand.api.structure.node.CommandNode; + +import java.util.Iterator; +import java.util.Map; + +public interface KenCommandApi { + + void invoke(CommandNode node, T sender, String[] args); + + CommandExecutor processLiterals(CommandNode node, Iterator argsIterator); + + Map> parseArguments(CommandNode node, Iterator argsIterator); +} diff --git a/src/main/java/de/kencommand/api/parsing/ParsedArgument.java b/src/main/java/de/kencommand/api/parsing/ParsedArgument.java deleted file mode 100644 index 52ddc14..0000000 --- a/src/main/java/de/kencommand/api/parsing/ParsedArgument.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.kencommand.api.parsing; - -import de.kencommand.api.processing.CommandContext; -import de.kencommand.api.structure.argument.CommandArgument; - -public interface ParsedArgument, V> { - - V getValue(); - - CommandArgument getArgument(); -} diff --git a/src/main/java/de/kencommand/api/processing/CommandContext.java b/src/main/java/de/kencommand/api/processing/CommandContext.java index 6375503..761e346 100644 --- a/src/main/java/de/kencommand/api/processing/CommandContext.java +++ b/src/main/java/de/kencommand/api/processing/CommandContext.java @@ -1,34 +1,17 @@ package de.kencommand.api.processing; -import de.kencommand.api.parsing.ParsedArgument; -import de.kentoj.scrow.bukkit.command.exception.CommandInvocationException; -import de.kentoj.scrow.bukkit.command.literal.CommandArgument; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; - public interface CommandContext { T getSender(); /** * @return Object that is parsed from the raw argument - * @throws CommandInvocationException if no value given and no default value supplied + * @throws RuntimeException if no value given and no default value supplied */ - ParsedArgument getArgData(String name); + ParsedArgument getParsedArgument(String name); @SuppressWarnings("unchecked") - default T getArgData(CommandArgument arg) { - return (T) getArgData(arg.getName()); - } - - @SuppressWarnings("unchecked") - default T getArg(String name) { - return (T) getArgData(name).getValue(); - } - - @SuppressWarnings("unchecked") - default T getArg(CommandArgument arg) { - return (T) getArgData(arg.getName()).getValue(); + default V getArg(String name) { + return (V) getParsedArgument(name).getValue(); } } diff --git a/src/main/java/de/kencommand/api/processing/CommandExecutor.java b/src/main/java/de/kencommand/api/processing/CommandExecutor.java index 1f8f70e..65e57c6 100644 --- a/src/main/java/de/kencommand/api/processing/CommandExecutor.java +++ b/src/main/java/de/kencommand/api/processing/CommandExecutor.java @@ -1,6 +1,6 @@ package de.kencommand.api.processing; -public interface CommandExecutor { +public interface CommandExecutor { - void execute(S ctx); + void execute(CommandContext ctx); } diff --git a/src/main/java/de/kencommand/api/processing/ParsedArgument.java b/src/main/java/de/kencommand/api/processing/ParsedArgument.java new file mode 100644 index 0000000..13c4e06 --- /dev/null +++ b/src/main/java/de/kencommand/api/processing/ParsedArgument.java @@ -0,0 +1,10 @@ +package de.kencommand.api.processing; + +import de.kencommand.api.structure.argument.CommandArgument; + +public interface ParsedArgument { + + V getValue(); + + CommandArgument getArgument(); +} diff --git a/src/main/java/de/kencommand/api/structure/argument/ArgumentType.java b/src/main/java/de/kencommand/api/structure/argument/ArgumentType.java index e6e1fdd..c73d036 100644 --- a/src/main/java/de/kencommand/api/structure/argument/ArgumentType.java +++ b/src/main/java/de/kencommand/api/structure/argument/ArgumentType.java @@ -1,10 +1,8 @@ package de.kencommand.api.structure.argument; -import de.kencommand.api.processing.CommandContext; - public interface ArgumentType { V parseInput(String string); - SuggestionProvider> defaultSuggestionProvider(); + SuggestionProvider defaultSuggestionProvider(); } diff --git a/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java b/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java index 861987e..3b6a0f8 100644 --- a/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java +++ b/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java @@ -4,7 +4,7 @@ import de.kencommand.api.processing.CommandContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface CommandArgument, V> { +public interface CommandArgument { String getId(); @@ -14,10 +14,10 @@ public interface CommandArgument, V> { @Nullable T getDefaultValue(); - void setSuggestionProvider(@Nullable SuggestionProvider suggestionProvider); + void setSuggestionProvider(@Nullable SuggestionProvider suggestionProvider); /** * @return the explicitly set SuggestionProvider or the default suggestions for the type if unset/null */ - @NotNull SuggestionProvider getSuggestionProvider(); + @NotNull SuggestionProvider getSuggestionProvider(); } diff --git a/src/main/java/de/kencommand/api/structure/argument/SuggestionProvider.java b/src/main/java/de/kencommand/api/structure/argument/SuggestionProvider.java index a00c761..9f579dc 100644 --- a/src/main/java/de/kencommand/api/structure/argument/SuggestionProvider.java +++ b/src/main/java/de/kencommand/api/structure/argument/SuggestionProvider.java @@ -4,7 +4,7 @@ import de.kencommand.api.processing.CommandContext; import java.util.Set; -public interface SuggestionProvider> { +public interface SuggestionProvider { - Set suggest(S context); + Set suggest(CommandContext context); } diff --git a/src/main/java/de/kencommand/api/structure/node/ArgumentNode.java b/src/main/java/de/kencommand/api/structure/node/ArgumentNode.java index 6228d31..94a3a2b 100644 --- a/src/main/java/de/kencommand/api/structure/node/ArgumentNode.java +++ b/src/main/java/de/kencommand/api/structure/node/ArgumentNode.java @@ -1,13 +1,12 @@ package de.kencommand.api.structure.node; -import de.kencommand.api.processing.CommandContext; import de.kencommand.api.structure.argument.CommandArgument; import java.util.Set; -public interface ArgumentNode> { +public interface ArgumentNode { - void addArgument(CommandArgument argument); + void addArgument(CommandArgument argument); - Set> getArguments(); + Set> getArguments(); } diff --git a/src/main/java/de/kencommand/api/structure/node/CommandNode.java b/src/main/java/de/kencommand/api/structure/node/CommandNode.java index 4a4188f..e9b280d 100644 --- a/src/main/java/de/kencommand/api/structure/node/CommandNode.java +++ b/src/main/java/de/kencommand/api/structure/node/CommandNode.java @@ -1,21 +1,19 @@ package de.kencommand.api.structure.node; -import de.kencommand.api.processing.CommandContext; import de.kencommand.api.processing.CommandExecutor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @param type of command sender - * @param type of command context */ -public interface CommandNode> extends LiteralNode, ArgumentNode { +public interface CommandNode extends ArgumentNode, LiteralNode { @NotNull String[] getNames(); - void setExecutor(@Nullable CommandExecutor executor); + void setExecutor(@Nullable CommandExecutor executor); - @Nullable CommandExecutor getExecutor(); + @Nullable CommandExecutor getExecutor(); void setDescription(@Nullable String description); diff --git a/src/main/java/de/kencommand/api/structure/node/LiteralNode.java b/src/main/java/de/kencommand/api/structure/node/LiteralNode.java index a2a3622..4239456 100644 --- a/src/main/java/de/kencommand/api/structure/node/LiteralNode.java +++ b/src/main/java/de/kencommand/api/structure/node/LiteralNode.java @@ -1,15 +1,15 @@ package de.kencommand.api.structure.node; -import de.kencommand.api.processing.CommandContext; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Set; -public interface LiteralNode> { +public interface LiteralNode { - void addLiteral(@NotNull CommandNode commandNode); + void addLiteral(@NotNull CommandNode commandNode); - CommandNode getLiteral(@NotNull String name); + @Nullable CommandNode getLiteral(@NotNull String name); - @NotNull Set> getLiterals(); + @NotNull Set> getLiterals(); } diff --git a/src/main/java/de/kencommand/impl/KenCommandApiImpl.java b/src/main/java/de/kencommand/impl/KenCommandApiImpl.java new file mode 100644 index 0000000..a6918db --- /dev/null +++ b/src/main/java/de/kencommand/impl/KenCommandApiImpl.java @@ -0,0 +1,66 @@ +package de.kencommand.impl; + +import de.kencommand.api.KenCommandApi; +import de.kencommand.api.processing.CommandExecutor; +import de.kencommand.api.processing.ParsedArgument; +import de.kencommand.api.structure.argument.CommandArgument; +import de.kencommand.api.structure.node.CommandNode; +import de.kencommand.impl.processing.CommandContextImpl; +import de.kencommand.impl.processing.ParsedArgumentImpl; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +@RequiredArgsConstructor +public class KenCommandApiImpl implements KenCommandApi { + + @Override + public void invoke(CommandNode node, T sender, String[] args) { + var iter = Arrays.stream(args).iterator(); + + var executor = processLiterals(node, iter); + var parsedArguments = parseArguments(node, iter); + executor.execute(new CommandContextImpl<>(sender, parsedArguments)); + } + + @Override + public CommandExecutor processLiterals(CommandNode commandNode, Iterator iter) { + if (!iter.hasNext()) { + // literals/arguments are optional if the node itself is executable + if (commandNode.getExecutor() == null) throw new RuntimeException("no literal given but required"); + // TODO parse arguments for executor ig, or rather do that in a separate method + return commandNode.getExecutor(); + } + + final var arg = iter.next(); + // TODO rethink + final var literal = commandNode.getLiteral(arg); + if (literal == null) { + throw new RuntimeException("Invalid literal: " + arg); + } + return processLiterals(literal, iter); + } + + @Override + public Map> parseArguments(CommandNode commandNode, Iterator iter) { + Map> parsedArguments = new HashMap<>(); + for (CommandArgument argument : commandNode.getArguments()) { + @SuppressWarnings("unchecked") + var arg = ((CommandArgument) argument); + + if (!iter.hasNext()) { + var defaultValue = arg.getDefaultValue(); + if (defaultValue == null) throw new RuntimeException("no argument given but required"); + parsedArguments.put(arg.getId(), new ParsedArgumentImpl<>(defaultValue, arg)); + continue; + } + + var parsedArg = arg.getType().parseInput(iter.next()); + parsedArguments.put(arg.getId(), new ParsedArgumentImpl<>(parsedArg, arg)); + } + return parsedArguments; + } +} diff --git a/src/main/java/de/kencommand/impl/parsing/CommandNodeParser.java b/src/main/java/de/kencommand/impl/parsing/CommandNodeParser.java deleted file mode 100644 index 422e91f..0000000 --- a/src/main/java/de/kencommand/impl/parsing/CommandNodeParser.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.kencommand.impl.parsing; - -import de.kencommand.api.processing.CommandContext; -import de.kencommand.api.processing.CommandExecutor; -import de.kencommand.api.structure.node.CommandNode; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -@RequiredArgsConstructor -public class CommandNodeParser> { - - public CommandExecutor parse(CommandNode commandNode, String[] args) { - var iter = Arrays.stream(args).iterator(); - - while (true) { - if (!iter.hasNext()) { - // literals/arguments are optional if the node itself is executable - if (commandNode.getExecutor() == null) throw new RuntimeException("no literal given but required"); - // TODO parse arguments for executor ig, or rather do that in a separate method - return commandNode.getExecutor(); - } - - final var arg = iter.next(); - // TODO rethink - return parse(commandNode.getLiteral(arg), args); - } - } -} diff --git a/src/main/java/de/kencommand/impl/processing/CommandContextImpl.java b/src/main/java/de/kencommand/impl/processing/CommandContextImpl.java new file mode 100644 index 0000000..9e8348d --- /dev/null +++ b/src/main/java/de/kencommand/impl/processing/CommandContextImpl.java @@ -0,0 +1,26 @@ +package de.kencommand.impl.processing; + +import de.kencommand.api.processing.CommandContext; +import de.kencommand.api.processing.ParsedArgument; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +@RequiredArgsConstructor +public class CommandContextImpl implements CommandContext { + @Getter + private final T sender; + @Getter + private final Map> parsedArguments; + + @Override + public ParsedArgument getParsedArgument(String name) { + try { + //noinspection unchecked + return (ParsedArgument) parsedArguments.get(name); + } catch (ClassCastException e) { + throw new RuntimeException("requested argument with wrong type", e); + } + } +} diff --git a/src/main/java/de/kencommand/impl/processing/ParsedArgumentImpl.java b/src/main/java/de/kencommand/impl/processing/ParsedArgumentImpl.java new file mode 100644 index 0000000..0412ed1 --- /dev/null +++ b/src/main/java/de/kencommand/impl/processing/ParsedArgumentImpl.java @@ -0,0 +1,11 @@ +package de.kencommand.impl.processing; + +import de.kencommand.api.processing.ParsedArgument; +import de.kencommand.api.structure.argument.CommandArgument; +import lombok.Data; + +@Data +public class ParsedArgumentImpl implements ParsedArgument { + final V value; + final CommandArgument argument; +} diff --git a/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java b/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java index db39e82..7476547 100644 --- a/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java +++ b/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java @@ -14,26 +14,26 @@ import java.util.HashSet; import java.util.Set; @RequiredArgsConstructor -public class CommandNodeImpl> implements CommandNode { +public class CommandNodeImpl implements CommandNode { @Getter private final String[] names; @Getter - private final Set> literals = new HashSet<>(); + private final Set> literals = new HashSet<>(); @Getter - private final Set> arguments = new HashSet<>(); + private final Set> arguments = new HashSet<>(); @Getter @Setter - private @Nullable CommandExecutor executor; + private @Nullable CommandExecutor executor; @Getter @Setter private String description; @Override - public void addLiteral(@NotNull CommandNode commandNode) { + public void addLiteral(@NotNull CommandNode commandNode) { for (String name : commandNode.getNames()) { if (getLiteral(name) != null) throw new IllegalArgumentException("literal with same name is already added"); } @@ -41,7 +41,7 @@ public class CommandNodeImpl> implements CommandN } @Override - public CommandNode getLiteral(@NotNull String name) { + public CommandNode getLiteral(@NotNull String name) { for (var literal : literals) { for (String literalName : literal.getNames()) { if (literalName.equalsIgnoreCase(name)) return literal; @@ -51,7 +51,7 @@ public class CommandNodeImpl> implements CommandN } @Override - public void addArgument(CommandArgument argument) { + public void addArgument(CommandArgument argument) { if (arguments.stream() .anyMatch(arg -> arg.getId().equals(argument.getId())) ) {