refactor ig

This commit is contained in:
kento2 2026-08-04 02:30:41 +02:00
parent ef32f9dbc4
commit 336ac4cad5
54 changed files with 528 additions and 444 deletions

View file

@ -6,7 +6,7 @@
<fork_state>
<option name="name" value="bazelbuild" />
<option name="version" value="9.2.0" />
<option name="lastUpdated" value="1785684742087" />
<option name="lastUpdated" value="1785771270076" />
</fork_state>
</entry>
</forks>

147
.idea/workspace.xml generated
View file

@ -7,15 +7,18 @@
<option name="bazelBin" value="$USER_HOME$/.cache/bazel/_bazel_a/ddb0601c3c3f894317d0e9fe2e5bde13/execroot/_main/bazel-out/k8-fastbuild/bin" />
<option name="execRoot" value="$USER_HOME$/.cache/bazel/_bazel_a/ddb0601c3c3f894317d0e9fe2e5bde13/execroot/_main" />
</component>
<component name="BazelProjectContextService">
<option name="bazelBin" value="$USER_HOME$/.cache/bazel/_bazel_a/ddb0601c3c3f894317d0e9fe2e5bde13/execroot/_main/bazel-out/k8-fastbuild/bin" />
<option name="bazelReleaseVersion" value="9.2.0" />
<option name="execRoot" value="$USER_HOME$/.cache/bazel/_bazel_a/ddb0601c3c3f894317d0e9fe2e5bde13/execroot/_main" />
<option name="workspaceName" value="_main" />
</component>
<component name="BazelProjectProperties">
<option name="bazelProject" value="true" />
<option name="defaultJdkName" value="rules_jvm_external-jdk-b3ed7" />
<option name="defaultJdkName" value="KenCommandAPI-jdk-e101e" />
<option name="initialized" value="true" />
<option name="rootDirUrl" value="file://$PROJECT_DIR$" />
</component>
<component name="BazelProjectSettingsService">
<option name="projectViewPathUri" value="file://$PROJECT_DIR$/.bazelbsp/.bazelproject" />
</component>
<component name="BazelRepoMappingService">
<option name="apparentRepoNameToCanonicalName">
<map>
@ -37,11 +40,61 @@
</option>
</component>
<component name="ChangeListManager">
<list default="true" id="6414223f-1761-4683-97f5-9dab59d6c44a" name="Changes" comment="works">
<list default="true" id="6414223f-1761-4683-97f5-9dab59d6c44a" name="Changes" comment="make velocity work">
<change afterPath="$PROJECT_DIR$/bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommand.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentImpl.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentSpecImpl.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/literal/LiteralImpl.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/literal/RootLiteral.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/literal/RootLiteralImpl.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommand.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/bazelVersionCache.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/bazelVersionCache.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MODULE.bazel" beforeDir="false" afterPath="$PROJECT_DIR$/MODULE.bazel" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/BUILD" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-velocity/BUILD" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/build.gradle.kts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/BUILD" beforeDir="false" afterPath="$PROJECT_DIR$/bukkit/BUILD" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommand.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/TabCompleteListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/bukkit/src/main/java/de/kentoj/kencommandapi/TabCompleteListener.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/suggestionprovider/PlayerSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/bukkit/src/main/java/de/kentoj/kencommandapi/suggestionprovider/PlayerSuggestionProvider.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/type/OfflinePlayerArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/bukkit/src/main/java/de/kentoj/kencommandapi/type/OfflinePlayerArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/type/PlayerArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/bukkit/src/main/java/de/kentoj/kencommandapi/type/PlayerArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/BUILD" beforeDir="false" afterPath="$PROJECT_DIR$/core/BUILD" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/CommandHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/CommandHandler.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/ArgumentRequirement.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/ArgumentRequirement.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/ArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/ArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgument.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgument.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentImpl.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentSpec.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentSpec.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentSpecBuilder.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentSpecBuilder.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/CommandArgumentSpecImpl.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/types/IntegerArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/types/IntegerArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/types/StringArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/argument/types/StringArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandContext.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandContext.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandExecutor.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandExecutor.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/SyncCommandExecutor.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/invocation/SyncCommandExecutor.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/literal/Literal.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/literal/Literal.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/literal/LiteralBuilder.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/literal/LiteralBuilder.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/literal/LiteralImpl.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/HasPermissionMethod.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/platform/HasPermissionMethod.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/MessageStyle.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/platform/MessageStyle.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/PlainMessageStyle.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/platform/PlainMessageStyle.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/SendMessageMethod.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/platform/SendMessageMethod.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/suggestion/NoSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/suggestion/NoSuggestionProvider.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/suggestion/SuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/api/suggestion/SuggestionProvider.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandContextImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/internal/CommandContextImpl.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/CommandParseHelper.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/internal/parser/CommandParseHelper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/InvocationCommandParser.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/internal/parser/InvocationCommandParser.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/SuggestionCommandParser.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/de/kentoj/kencommandapi/internal/parser/SuggestionCommandParser.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/ENV.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/test/java/de/kentoj/kencommandapi/api/parser/ENV.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/SuggestionCommandParserTest.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/test/java/de/kentoj/kencommandapi/api/parser/SuggestionCommandParserTest.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/BUILD" beforeDir="false" afterPath="$PROJECT_DIR$/velocity/BUILD" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommand.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/suggestionprovider/PlayerSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/velocity/src/main/java/de/kentoj/kencommandapi/suggestionprovider/PlayerSuggestionProvider.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/type/PlayerArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/velocity/src/main/java/de/kentoj/kencommandapi/type/PlayerArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/third_party/BUILD" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/third_party/libs.versions.toml" beforeDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -139,8 +192,14 @@
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Bazel.//bukkit:bukkit.publish.executor": "Run",
"Bazel.//core:core.publish.executor": "Run",
"Bazel.//kencommandapi-velocity:velocity.publish.executor": "Run",
"Bazel.//velocity:velocity.publish.executor": "Run",
"Bazel.Run //kencommandapi-bukkit:bukkit.publish.executor": "Run",
"Bazel.Run //kencommandapi-core:core.publish.executor": "Run",
"Bazel.Run //kencommandapi-core:export.publish.executor": "Run",
"Bazel.Run //kencommandapi-velocity:velocity.publish.executor": "Run",
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [:kencommandapi-core:de.kentoj.kencommandapi.Main.main()].executor": "Run",
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [build].executor": "Run",
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [publish].executor": "Run",
@ -166,11 +225,17 @@
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
"RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"bazel.project.detector.is.bazel.project": "true",
"codeWithMe.voiceChat.enabledByDefault": "false",
"com.intellij.ide.FileNotInSourceRootChecker.no.check": "true",
"git-widget-placeholder": "master",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "/home/a/src/random/rules_jvm_external",
"node.js.detected.package.jshint": "true",
"node.js.selected.package.jshint": "",
"nodejs_package_manager_path": "npm",
"project.structure.last.edited": "Modules",
"project.structure.proportion": "0.15",
"project.structure.side.proportion": "0.6268199",
@ -202,11 +267,11 @@
<recent name="de.kentoj.kencommandapi.api.invocation" />
</key>
<key name="CopyClassDialog.RECENTS_KEY">
<recent name="de.kentoj.kencommandapi.api.literal" />
<recent name="de.kentoj.kencommandapi.api.parser2" />
<recent name="de.kentoj.kencommandapi.api.invocation" />
<recent name="de.kentoj.kencommandapi.internal" />
<recent name="de.kentoj.kencommandapi.api" />
<recent name="de.kentoj.kencommandapi.impl" />
</key>
</component>
<component name="RunAnythingCache">
@ -226,7 +291,6 @@
<command value="bazel build //kencommandapi-core:core --nojava_header_compilation" />
<command value="bazel build //kencommandapi-bukkit:bukkit" />
<command value="bazel build //kencommandapi-bukkit:bukkit --nojava_header_compilation" />
<command value="bazel clean" />
<command value="bazel sync --only=maven --verbose_failures" />
<command value="bazel build //kencommandapi-core:core-lib" />
<command value="bazel build //kencommandapi-core:core-lib --verbose" />
@ -237,39 +301,41 @@
<command value="bazel -v build //kencommandapi-core:core-lib --subcommands " />
<command value="bazel build //kencommandapi-core:core-lib --subcommands " />
<command value="bazel build //kencommandapi-core:core-lib --subcommands --verbose_failures" />
<command value="bazel clean --expunge" />
<command value="bazel shutdown" />
<command value="bazel clean" />
<command value="bazel clean --expunge" />
<command value="bazel build bukkit" />
</option>
</component>
<component name="RunManager" selected="Bazel.Run //kencommandapi-velocity:velocity.publish">
<configuration name="Run //kencommandapi-bukkit:bukkit.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider">
<bsp-target>@//kencommandapi-bukkit:bukkit.publish</bsp-target>
<component name="RunManager" selected="Bazel.//bukkit:bukkit.publish">
<configuration name="//bukkit:bukkit.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider" check-visibility="true">
<bsp-target>@//bukkit:bukkit.publish</bsp-target>
<handler-state />
</bsp-state>
<method v="2" />
</configuration>
<configuration name="Run //kencommandapi-core:core.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider">
<bsp-target>@//kencommandapi-core:core.publish</bsp-target>
<configuration name="//core:core.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider" check-visibility="true">
<bsp-target>@//core:core.publish</bsp-target>
<handler-state />
</bsp-state>
<method v="2" />
</configuration>
<configuration name="Run //kencommandapi-core:export.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider">
<bsp-target>@//kencommandapi-core:export.publish</bsp-target>
<handler-state />
</bsp-state>
<method v="2" />
</configuration>
<configuration name="Run //kencommandapi-velocity:velocity.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider">
<configuration name="//kencommandapi-velocity:velocity.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider" check-visibility="true">
<bsp-target>@//kencommandapi-velocity:velocity.publish</bsp-target>
<handler-state />
</bsp-state>
<method v="2" />
</configuration>
<configuration name="//velocity:velocity.publish" type="BazelRunConfigurationType" temporary="true">
<bsp-state handler-provider-id="GenericRunHandlerProvider" check-visibility="true">
<bsp-target>@//velocity:velocity.publish</bsp-target>
<handler-state />
</bsp-state>
<method v="2" />
</configuration>
<configuration name="KenCommandAPI [publishAllPublicationsToScrowRepository]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
@ -288,8 +354,11 @@
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
<configuration default="true" type="JetRunConfigurationType">
@ -305,14 +374,22 @@
</configuration>
<recent_temporary>
<list>
<item itemvalue="Bazel.Run //kencommandapi-velocity:velocity.publish" />
<item itemvalue="Bazel.Run //kencommandapi-bukkit:bukkit.publish" />
<item itemvalue="Bazel.Run //kencommandapi-core:core.publish" />
<item itemvalue="Bazel.Run //kencommandapi-bukkit:bukkit.publish" />
<item itemvalue="Bazel.Run //kencommandapi-core:export.publish" />
<item itemvalue="Bazel.//bukkit:bukkit.publish" />
<item itemvalue="Bazel.//core:core.publish" />
<item itemvalue="Bazel.//velocity:velocity.publish" />
<item itemvalue="Bazel.//kencommandapi-velocity:velocity.publish" />
<item itemvalue="Bazel.//kencommandapi-velocity:velocity.publish" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-jdk-30f59d01ecdd-63390994e64e-intellij.indexing.shared.core-IU-262.8665.337" />
<option value="bundled-js-predefined-d6986cc7102b-4abd2a77f808-JavaScript-IU-262.8665.337" />
</set>
</attachedChunks>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="6414223f-1761-4683-97f5-9dab59d6c44a" name="Changes" comment="" />
@ -548,6 +625,9 @@
<option name="localTasksCounter" value="29" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
@ -575,6 +655,7 @@
<MESSAGE value="BAZEL" />
<MESSAGE value="BAZEL + some code" />
<MESSAGE value="works" />
<option name="LAST_COMMIT_MESSAGE" value="works" />
<MESSAGE value="make velocity work" />
<option name="LAST_COMMIT_MESSAGE" value="make velocity work" />
</component>
</project>

View file

@ -1,13 +1,16 @@
## TODO
CI/CD to publish automatically
## Build
after installing bazel:
```shell
bazel build //kencommandapi-bukkit:bukkit
bazel build //kencommandapi-core:core
bazel build //bukkit
bazel build //core
bazel build //velocity
```
can't compile -velocity module yet.
## Limitations & Bugs
- argument's can't require specific permissions.
@ -29,12 +32,12 @@ arguments can have suggestions.
To allow the use of `/feed` without giving a user's name, i.e. to make the argument optional, we need to assign the
user-argument a default value.
## An example command
### An example command
Let's say we want to make a command that allows seeing how many coins another User has.
If we don't specify a user, it should instead show the coins the sender has.
## As a tree
### As a tree
Visualized as a tree, we have a Node/Literal `coins` with an alias `balance` with an optional argument called `user`.
To make an argument optional, it must have a default value.
@ -45,38 +48,42 @@ literal:coins/balance
- has executor:getCoins
```
## As code
### As code
```java
import de.kentoj.kencommandapi.api.literal.RootLiteral;
/**
* Show the amount coins a user has.
* If no user is given, it should show the amount the sender of the command has.
*/
@NoArgsConstructor(access = AccessLevel.NONE)
public class CoinsCommand {
@Getter
private final Literal<User> rootLiteral;
private final RootLiteral<User> rootLiteral;
private final CommandArgumentSpec<User, User> userArg;
public CoinsCommand() {
userArg = CommandArgumentSpec.builder("user", new UserArgumentType<User>())
.withRequirement(p -> !p.hasPermission("economy.immune.getcoins"),
"you can't see that player's balance")
.withDefaultValue(CommandContext::getSender)
.withDefaultValue(CommandContext::sender)
.build();
rootLiteral = Literal.<User>builder("coins", "balance")
.withStyle(MessageStyle.PLAIN)
.withPermission("economy.command.coins")
.withArgument(userArg)
.withSyncExecutor(this::getCoins)
.build();
.asRootLiteral(MessageStyle.PLAIN);
}
private Result<Object, String> getCoins(CommandContext<User> ctx) {
var player = ctx.getArg(userArg);
ctx.getSender().sendMessage(player.getName() + " has " + player.getCoins() + " coins");
var user = ctx.getArg(userArg);
ctx.getSender().sendMessage(user.name() + " has " + user.coins() + " coins");
return Results.success(new Object());
}
public RootLiteral<User> rootLiteral() {
return rootLiteral;
}
}
```
@ -87,5 +94,5 @@ Additionally, we can also a Requirement in the CommandArgumentSpec.
The registration of the command is platform-dependant. Typically, a class called CommandAPI can be used.
```java
CommandAPI api = new CommandAPI();
register(new CoinsCommand().getRootLiteral());
register(new CoinsCommand().rootLiteral());
```

View file

@ -5,13 +5,11 @@ java_export(
maven_coordinates = "de.kentoj.scrow:kencommandapi-bukkit:0.34-SNAPSHOT",
srcs = glob(["src/main/**/*.java"]),
deps = [
"//kencommandapi-core:core",
artifact("org.projectlombok:lombok"),
"//core",
artifact("org.jetbrains:annotations"),
artifact("io.papermc.paper:paper-api:[26.2.build,)"),
artifact("io.papermc.paper:paper-api"),
],
exports = [
"//kencommandapi-core:core",
"//core",
],
plugins = [ "//third_party:lombok_plugin" ],
)

View file

@ -0,0 +1,40 @@
package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.stream.Stream;
public class BukkitKenCommand<T extends CommandSender> extends Command {
private final RootLiteral<T> rootLiteral;
private final CommandHandler<T> commandHandler;
private final Class<T> senderType;
protected BukkitKenCommand(CommandHandler<T> commandHandler, RootLiteral<T> rootLiteral, Class<T> senderType) {
super(rootLiteral.names()[0]);
this.commandHandler = commandHandler;
this.rootLiteral = rootLiteral;
this.senderType = senderType;
this.setAliases(Arrays.asList(rootLiteral.names()));
this.setPermission(rootLiteral.permission());
}
@Override
public boolean execute(@NotNull CommandSender commandSender, @NotNull String commandLabel, @NotNull String[] args) {
if (!senderType.isInstance(commandSender)) {
commandSender.sendMessage(MessageStyle.PLAIN.err("You can't use that command"));
return true;
}
T sender = senderType.cast(commandSender);
commandHandler.invoke(rootLiteral, sender, Stream.of(args).filter(str -> !str.isEmpty()));
return true;
}
}

View file

@ -1,7 +1,7 @@
package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.SimpleCommandMap;
@ -13,15 +13,17 @@ import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class CommandAPI {
public class CommandAPI<T extends CommandSender> {
private final CommandHandler<CommandSender> commandHandler;
private final List<Literal<CommandSender>> registeredNodes = new ArrayList<>();
private final CommandHandler<T> commandHandler;
private final List<RootLiteral<T>> registeredNodes = new ArrayList<>();
private final SimpleCommandMap commandMap;
private final Class<T> senderType;
public CommandAPI(Plugin plugin) {
public CommandAPI(Plugin plugin, Class<T> senderType) {
this.senderType = senderType;
this.commandHandler = new CommandHandler<>(CommandSender::sendMessage, Permissible::hasPermission);
Bukkit.getPluginManager().registerEvents(new TabCompleteListener(this, commandHandler), plugin);
Bukkit.getPluginManager().registerEvents(new TabCompleteListener<>(this, commandHandler, senderType), plugin);
try {
Field field = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
@ -32,17 +34,17 @@ public class CommandAPI {
}
}
@Nullable Literal<CommandSender> getRegistered(String name) {
@Nullable RootLiteral<T> getRegistered(String name) {
for (var node : registeredNodes) {
for (String nodeName : node.getNames()) {
for (String nodeName : node.names()) {
if (nodeName.equals(name)) return node;
}
}
return null;
}
public void register(Literal<CommandSender> rootNode) {
public void register(RootLiteral<T> rootNode) {
registeredNodes.add(rootNode);
commandMap.register(rootNode.getNames()[0], new BukkitKenCommand(commandHandler, rootNode));
commandMap.register(rootNode.names()[0], new BukkitKenCommand<>(commandHandler, rootNode, senderType));
}
}

View file

@ -2,18 +2,23 @@ package de.kentoj.kencommandapi;
import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent;
import de.kentoj.kencommandapi.api.CommandHandler;
import lombok.RequiredArgsConstructor;
import org.bukkit.command.CommandSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.Arrays;
@RequiredArgsConstructor
public class TabCompleteListener implements Listener {
public class TabCompleteListener<T extends CommandSender> implements Listener {
private final CommandAPI commandAPI;
private final CommandHandler<CommandSender> commandHandler;
private final CommandAPI<T> commandAPI;
private final CommandHandler<T> commandHandler;
private final Class<T> senderType;
public TabCompleteListener(CommandAPI<T> commandAPI, CommandHandler<T> commandHandler, Class<T> senderType) {
this.commandAPI = commandAPI;
this.commandHandler = commandHandler;
this.senderType = senderType;
}
@EventHandler(ignoreCancelled = true)
public void onAsyncTabComplete(AsyncTabCompleteEvent ev) {
@ -26,11 +31,16 @@ public class TabCompleteListener implements Listener {
// commands can be called with a '<plugin name>:' prefix. strip it.
int l = label.indexOf(':');
if (l >= 0)
label = label.substring(l+1);
label = label.substring(l + 1);
}
var literal = commandAPI.getRegistered(label);
if (literal == null) return;
if (!senderType.isInstance(ev.getSender()))
return;
T sender = senderType.cast(ev.getSender());
ev.setHandled(true);
ev.setCompletions(commandHandler.getSuggestions(literal, ev.getSender(), Arrays.copyOfRange(args, 1, args.length), ev.getBuffer().endsWith(" ")));
ev.setCompletions(commandHandler.getSuggestions(literal, sender, Arrays.copyOfRange(args, 1, args.length), ev.getBuffer().endsWith(" ")));
}
}

View file

@ -2,12 +2,11 @@ package de.kentoj.kencommandapi.suggestionprovider;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class PlayerSuggestionProvider<T> implements SuggestionProvider<T> {
public final class PlayerSuggestionProvider<T> implements SuggestionProvider<T> {
@Override
public List<String> suggest(T __) {
return Bukkit.getOnlinePlayers().stream()

View file

@ -3,30 +3,27 @@ package de.kentoj.kencommandapi.type;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import java.util.UUID;
@NoArgsConstructor
public class OfflinePlayerArgumentType<T> implements ArgumentType<T, OfflinePlayer> {
// TODO make work with player names on offline players
@Override
public OfflinePlayer parseInputUnchecked(String string) {
OfflinePlayer player = Bukkit.getPlayerExact(string);
if (player == null) {
// UUIDs are always 36 chars
if (string.length() == 36) {
try {
player = Bukkit.getOfflinePlayer(UUID.fromString(string));
return Bukkit.getOfflinePlayer(UUID.fromString(string));
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("not an UUID or online player");
throw new IllegalArgumentException("Invalid UUID");
}
}
if (!player.hasPlayedBefore() && !player.isOnline()) throw new IllegalArgumentException("Player not found");
OfflinePlayer player = Bukkit.getPlayerExact(string);
if (player == null || (!player.hasPlayedBefore() && !player.isOnline()))
throw new IllegalArgumentException("Player not found");
return player;
}

View file

@ -3,11 +3,9 @@ package de.kentoj.kencommandapi.type;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
import lombok.NoArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@NoArgsConstructor
public class PlayerArgumentType<T> implements ArgumentType<T, Player> {
@Override

View file

@ -6,7 +6,6 @@ java_export(
srcs = glob(["src/main/**/*.java"]),
visibility = ["//visibility:public"],
deps = [
artifact("org.projectlombok:lombok"),
artifact("com.leakyabstractions:result-api"),
artifact("com.leakyabstractions:result"),
artifact("org.jetbrains:annotations"),
@ -14,5 +13,4 @@ java_export(
artifact("org.slf4j:slf4j-api"),
artifact("net.kyori:adventure-api"),
],
plugins = [ "//third_party:lombok_plugin" ],
)

View file

@ -1,22 +1,19 @@
package de.kentoj.kencommandapi.api;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
import de.kentoj.kencommandapi.api.platform.SendMessageMethod;
import de.kentoj.kencommandapi.internal.parser.CommandParseHelper;
import de.kentoj.kencommandapi.internal.parser.InvocationCommandParser;
import de.kentoj.kencommandapi.internal.parser.SuggestionCommandParser;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
@RequiredArgsConstructor
public class CommandHandler<T> {
private final SendMessageMethod<T> sendMessageMethod;
private final InvocationCommandParser<T> invocationParser;
private final SuggestionCommandParser<T> suggestionParser;
@ -27,25 +24,24 @@ public class CommandHandler<T> {
suggestionParser = new SuggestionCommandParser<>(parseHelper);
}
public void invoke(Literal<T> rootLiteral, T sender, Stream<String> args) {
// FIXME uses rootLiteral's message style
public void invoke(RootLiteral<T> rootLiteral, T sender, Stream<String> args) {
invocationParser.parse(rootLiteral, sender, args.toList().iterator())
.ifSuccessOrElse(data -> exec(rootLiteral, data),
err -> sendMessageMethod.send(sender, rootLiteral.getMessageStyle().err(err)));
err -> sendMessageMethod.send(sender, rootLiteral.messageStyle().err(err)));
}
private void exec(Literal<T> rootLiteral, InvocationCommandParser<T>.ExecutionData data) {
var sender = data.getContext().getSender();
data.getExecutor().execute(data.getContext())
private void exec(RootLiteral<T> rootLiteral, InvocationCommandParser<T>.ExecutionData data) {
var ctx = data.context();
data.executor().execute(ctx)
.whenComplete((result, ex) -> {
if (ex != null)
sendMessageMethod.send(sender, rootLiteral.getMessageStyle().exception(ex));
sendMessageMethod.send(ctx.sender(), rootLiteral.messageStyle().exception(ex));
result.ifFailure(err ->
sendMessageMethod.send(sender, rootLiteral.getMessageStyle().err(err)));
sendMessageMethod.send(ctx.sender(), rootLiteral.messageStyle().err(err)));
});
}
public List<String> getSuggestions(Literal<T> rootNode, T sender, String[] args, boolean trailingSpace) {
public List<String> getSuggestions(RootLiteral<T> rootNode, T sender, String[] args, boolean trailingSpace) {
return suggestionParser.suggest(rootNode, sender, Arrays.stream(args).iterator(), trailingSpace);
}
}

View file

@ -1,14 +1,12 @@
package de.kentoj.kencommandapi.api.argument;
import lombok.Value;
import java.util.function.Predicate;
/**
* @param <V> type of the parsed argument value
*/
@Value
public class ArgumentRequirement<V> {
Predicate<V> predicate;
String message;
public record ArgumentRequirement<V>(
Predicate<V> predicate,
String message
) {
}

View file

@ -12,12 +12,12 @@ public interface ArgumentType<T, V> {
*
* @throws IllegalArgumentException if string invalid
* @see CommandArgumentSpec#parseInput(String)
* @see CommandArgumentSpecBuilder#addRequirement(Predicate, String)
* @see CommandArgumentSpecBuilder#withRequirement(Predicate, String)
*/
V parseInputUnchecked(String input) throws IllegalArgumentException;
/**
* @see CommandArgumentSpec#getSuggestionProvider()
* @see CommandArgumentSpec#suggestionProvider()
*/
SuggestionProvider<T> getDefaultSuggestionProvider();
@ -26,7 +26,7 @@ public interface ArgumentType<T, V> {
* 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 greedy() {
return false;
}
}

View file

@ -2,7 +2,7 @@ package de.kentoj.kencommandapi.api.argument;
public interface CommandArgument<T, V> {
V getValue();
V value();
CommandArgumentSpec<T, V> getArgument();
CommandArgumentSpec<T, V> argument();
}

View file

@ -0,0 +1,7 @@
package de.kentoj.kencommandapi.api.argument;
public record CommandArgumentImpl<T, V>(
V value,
CommandArgumentSpec<T, V> argument
) implements CommandArgument<T, V> {
}

View file

@ -13,20 +13,20 @@ public sealed interface CommandArgumentSpec<T, V> permits CommandArgumentSpecImp
return new CommandArgumentSpecBuilder<>(id, type);
}
String getId();
String id();
ArgumentType<T, V> getType();
ArgumentType<T, V> type();
/**
* @throws IllegalArgumentException if string invalid or if a requirement is not met
*/
V parseInput(String rawInput);
@Nullable Function<CommandContext<T>, V> getDefaultValueProvider();
@Nullable Function<CommandContext<T>, V> defaultValueProvider();
/**
* @return the explicitly set SuggestionProvider or the default suggestions for the type if unset/null
*/
/* explicit @NotNull to avoid confusion */
@NotNull SuggestionProvider<T> getSuggestionProvider();
@NotNull SuggestionProvider<T> suggestionProvider();
}

View file

@ -2,8 +2,6 @@ package de.kentoj.kencommandapi.api.argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@ -15,17 +13,19 @@ import java.util.function.Predicate;
* @param <T> type of the command sender
* @param <V> type of the value
*/
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
public class CommandArgumentSpecBuilder<T, V> {
private final String id;
private final ArgumentType<T, V> type;
private @Nullable Function<CommandContext<T>, V> defaultValueProvider;
private @Nullable SuggestionProvider<T> suggestionProvider;
private final List<ArgumentRequirement<V>> requirements = new ArrayList<>();
public CommandArgumentSpecBuilder(String id, ArgumentType<T, V> type) {
this.id = id;
this.type = type;
}
public CommandArgumentSpecBuilder<T, V> withRequirement(Predicate<V> predicate, String message) {
requirements.add(new ArgumentRequirement<>(predicate, message));
return this;

View file

@ -0,0 +1,38 @@
package de.kentoj.kencommandapi.api.argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.Function;
public record CommandArgumentSpecImpl<T, V>(
String id,
ArgumentType<T, V> type,
List<ArgumentRequirement<V>> requirements,
Function<CommandContext<T>, V> defaultValueProvider,
@Nullable SuggestionProvider<T> suggestionProvider
) implements CommandArgumentSpec<T, V> {
@Override
public V parseInput(String rawInput) {
var parsed = type.parseInputUnchecked(rawInput);
for (var requirement : requirements) {
if (!requirement.predicate().test(parsed))
throw new IllegalArgumentException(requirement.message());
}
return parsed;
}
@Override
public @Nullable Function<CommandContext<T>, V> defaultValueProvider() {
return defaultValueProvider;
}
@Override
public @NotNull SuggestionProvider<T> suggestionProvider() {
return suggestionProvider != null ? suggestionProvider : type.getDefaultSuggestionProvider();
}
}

View file

@ -2,16 +2,8 @@ package de.kentoj.kencommandapi.api.argument.types;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class StringArgumentType<T> implements ArgumentType<T, String> {
private final boolean isGreedy;
public StringArgumentType() {
this(false);
}
public record StringArgumentType<T>(boolean greedy) implements ArgumentType<T, String> {
@Override
public String parseInputUnchecked(String string) {
@ -22,9 +14,4 @@ public class StringArgumentType<T> implements ArgumentType<T, String> {
public SuggestionProvider<T> getDefaultSuggestionProvider() {
return SuggestionProvider.none();
}
@Override
public boolean isGreedy() {
return this.isGreedy;
}
}

View file

@ -7,7 +7,7 @@ import java.util.Map;
public interface CommandContext<T> {
T getSender();
T sender();
<V> CommandArgument<T, V> getParsedArgument(String id);
@ -17,7 +17,7 @@ public interface CommandContext<T> {
*/
@SuppressWarnings("unchecked")
default <V> V getArg(String id) {
return (V) getParsedArgument(id).getValue();
return (V) getParsedArgument(id).value();
}
/**
@ -26,12 +26,12 @@ public interface CommandContext<T> {
* @param <V> the type of the value of the argument
*/
default <V> V getArg(CommandArgumentSpec<T, V> arg) {
return getArg(arg.getId());
return getArg(arg.id());
}
default <V> CommandArgument<T, V> getParsedArgument(CommandArgumentSpec<T, V> arg) {
return getParsedArgument(arg.getId());
return getParsedArgument(arg.id());
}
Map<String, CommandArgument<T, ?>> getParsedArguments();
Map<String, CommandArgument<T, ?>> parsedArguments();
}

View file

@ -2,35 +2,30 @@ package de.kentoj.kencommandapi.api.literal;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.api.invocation.SyncCommandExecutor;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
public interface Literal<T> {
static <T> LiteralBuilder<T> builder(String... name) {
return new LiteralBuilder<>(name);
}
@NotNull String[] getNames();
@NotNull String[] names();
/**
* @return what the literal does
*/
@Nullable String getDescription();
@Nullable String description();
List<CommandArgumentSpec<T, ?>> getArguments();
List<CommandArgumentSpec<T, ?>> arguments();
@Nullable CommandExecutor<T> getExecutor();
@Nullable CommandExecutor<T> executor();
@Nullable Literal<T> getLiteral(@NotNull String name);
@NotNull List<Literal<T>> getLiterals();
@NotNull List<Literal<T>> literals();
@Nullable String getPermission();
MessageStyle getMessageStyle();
@Nullable String permission();
}

View file

@ -17,7 +17,6 @@ public final class LiteralBuilder<T> {
private @Nullable String description;
private @Nullable CommandExecutor<T> executor;
private @Nullable String permission;
private @Nullable MessageStyle messageStyle;
private final List<CommandArgumentSpec<T, ?>> arguments = new ArrayList<>();
private final List<Literal<T>> literals = new ArrayList<>();
@ -48,18 +47,13 @@ public final class LiteralBuilder<T> {
return this;
}
public LiteralBuilder<T> withStyle(MessageStyle messageStyle) {
this.messageStyle = messageStyle;
return this;
}
/**
* @throws IllegalArgumentException if there is already an argument with the same id
* @throws IllegalStateException if a greedy argument was added to the literal previously
*/
public LiteralBuilder<T> withArgument(CommandArgumentSpec<T, ?> argument) {
checkArgument(!hasGreedyArg(), "cannot add an argument after a greedy argument");
if (arguments.stream().anyMatch(arg -> arg.getId().equals(argument.getId())))
if (arguments.stream().anyMatch(arg -> arg.id().equals(argument.id())))
throw new IllegalArgumentException("cannot add multiple arguments with the same id");
this.arguments.add(argument);
@ -72,7 +66,7 @@ public final class LiteralBuilder<T> {
*/
public LiteralBuilder<T> withLiteral(Literal<T> literal) {
checkArgument(!hasGreedyArg(), "cannot add a literal after a greedy argument");
for (String name : literal.getNames())
for (String name : literal.names())
for (var l : literals)
if (l.getLiteral(name) != null)
throw new IllegalArgumentException("literal with same name already exists");
@ -81,20 +75,17 @@ public final class LiteralBuilder<T> {
return this;
}
public RootLiteral<T> asRootLiteral(MessageStyle messageStyle) {
return new RootLiteralImpl<>(names, description, literals, arguments, executor, permission, messageStyle);
}
public Literal<T> build() {
return new LiteralImpl<>(
names,
literals,
arguments,
executor,
permission,
messageStyle == null ? MessageStyle.PLAIN : messageStyle
);
return new LiteralImpl<>(names, description, literals, arguments, executor, permission);
}
private boolean hasGreedyArg() {
if (arguments.isEmpty()) return false;
var arg = arguments.getLast();
return arg != null && arg.getType().isGreedy();
return arg != null && arg.type().greedy();
}
}

View file

@ -0,0 +1,32 @@
package de.kentoj.kencommandapi.api.literal;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @param description what the literal does
*/
record LiteralImpl<T>(
String[] names,
String description,
List<Literal<T>> literals,
List<CommandArgumentSpec<T, ?>> arguments,
CommandExecutor<T> executor,
@Nullable String permission
) implements Literal<T> {
@Override
public @Nullable Literal<T> getLiteral(@NotNull String name) {
for (Literal<T> literal : literals) {
for (var literalName : literal.names()) {
if (literalName.equalsIgnoreCase(name))
return literal;
}
}
return null;
}
}

View file

@ -0,0 +1,8 @@
package de.kentoj.kencommandapi.api.literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
public sealed interface RootLiteral<T> extends Literal<T> permits RootLiteralImpl {
MessageStyle messageStyle();
}

View file

@ -0,0 +1,29 @@
package de.kentoj.kencommandapi.api.literal;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
record RootLiteralImpl<T>(
String[] names,
String description,
List<Literal<T>> literals,
List<CommandArgumentSpec<T, ?>> arguments,
CommandExecutor<T> executor,
@Nullable String permission,
MessageStyle messageStyle
) implements RootLiteral<T> {
@Override
public @Nullable Literal<T> getLiteral(@NotNull String name) {
for (var l : literals) {
for (var lName : l.names())
if (lName.equalsIgnoreCase(name))
return l;
}
return null;
}
}

View file

@ -1,10 +1,7 @@
package de.kentoj.kencommandapi.api.platform;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import net.kyori.adventure.text.Component;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
class PlainMessageStyle implements MessageStyle {
@Override
public Component ok(Component msg) {

View file

@ -1,15 +1,9 @@
package de.kentoj.kencommandapi.api.suggestion;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
class NoSuggestionProvider<T> implements SuggestionProvider<T> {
@Override
public List<String> suggest(T __) {
return Collections.emptyList();

View file

@ -2,17 +2,13 @@ package de.kentoj.kencommandapi.internal;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Map;
@RequiredArgsConstructor
public class CommandContextImpl<T> implements CommandContext<T> {
@Getter
private final T sender;
@Getter
private final Map<String, CommandArgument<T, ?>> parsedArguments;
public record CommandContextImpl<T>(
T sender,
Map<String, CommandArgument<T, ?>> parsedArguments
) implements CommandContext<T> {
@Override
public <V> CommandArgument<T, V> getParsedArgument(String id) {

View file

@ -2,17 +2,19 @@ package de.kentoj.kencommandapi.internal.parser;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
import lombok.RequiredArgsConstructor;
import java.util.Iterator;
@RequiredArgsConstructor
public final class CommandParseHelper<T> {
private final HasPermissionMethod<T> hasPermission;
public CommandParseHelper(HasPermissionMethod<T> hasPermission) {
this.hasPermission = hasPermission;
}
public boolean hasPermission(T sender, Literal<T> literal) {
if (literal.getPermission() == null) return true;
return hasPermission.test(sender, literal.getPermission());
if (literal.permission() == null) return true;
return hasPermission.test(sender, literal.permission());
}
public String parseInput(Iterator<String> tokenIter, boolean isGreedy) {

View file

@ -2,24 +2,28 @@ package de.kentoj.kencommandapi.internal.parser;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.argument.CommandArgumentImpl;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.argument.CommandArgumentImpl;
import de.kentoj.kencommandapi.internal.CommandContextImpl;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@RequiredArgsConstructor
import static java.util.Objects.requireNonNull;
public class InvocationCommandParser<T> {
private final CommandParseHelper<T> helper;
public InvocationCommandParser(CommandParseHelper<T> helper) {
this.helper = helper;
}
public Result<ExecutionData, String> parse(
Literal<T> rootLiteral,
T sender,
@ -31,13 +35,13 @@ public class InvocationCommandParser<T> {
while (true) {
{
var result = processArguments(currentLiteral, ctx, tokenIter)
.ifSuccess(ctx.getParsedArguments()::putAll);
.ifSuccess(ctx.parsedArguments()::putAll);
if (result.hasFailure())
return result.mapSuccess(__ -> null);
return result.mapSuccess(_ -> null);
}
if (!tokenIter.hasNext()) {
if (currentLiteral.getExecutor() == null)
if (currentLiteral.executor() == null)
return Results.failure("Literal expected");
break;
}
@ -50,7 +54,7 @@ public class InvocationCommandParser<T> {
currentLiteral = nextLiteral;
}
return Results.success(new ExecutionData(currentLiteral.getExecutor(), ctx));
return Results.success(new ExecutionData(currentLiteral.executor(), ctx));
}
private Result<Map<String, CommandArgument<T, ?>>, String> processArguments(
@ -60,33 +64,45 @@ public class InvocationCommandParser<T> {
) {
Map<String, CommandArgument<T, ?>> parsedArguments = new HashMap<>();
for (var _argument : literal.getArguments()) {
for (var _argument : literal.arguments()) {
@SuppressWarnings("unchecked")
var argument = ((CommandArgumentSpec<T, Object>) _argument);
Object value;
if (!tokenIter.hasNext()) {
if (argument.getDefaultValueProvider() == null)
return Results.failure("Argument expected: " + argument.getId());
value = argument.getDefaultValueProvider().apply(ctx);
if (argument.defaultValueProvider() == null)
return Results.failure("Argument expected: " + argument.id());
value = requireNonNull(argument.defaultValueProvider()).apply(ctx);
} else {
var input = helper.parseInput(tokenIter, argument.getType().isGreedy());
var input = helper.parseInput(tokenIter, argument.type().greedy());
try {
value = argument.parseInput(input);
} catch (IllegalArgumentException ex) {
return Results.failure("Illegal argument '" + input + "' for " + argument.getId() + ": " + ex.getMessage());
return Results.failure("Illegal argument '" + input + "' for " + argument.id() + ": " + ex.getMessage());
}
}
parsedArguments.put(argument.getId(), new CommandArgumentImpl<>(value, argument));
parsedArguments.put(argument.id(), new CommandArgumentImpl<>(value, argument));
}
return Results.success(parsedArguments);
}
@Value
public class ExecutionData {
CommandExecutor<T> executor;
CommandContext<T> context;
private final CommandExecutor<T> executor;
private final CommandContext<T> context;
public ExecutionData(CommandExecutor<T> executor, CommandContext<T> context) {
this.executor = executor;
this.context = context;
}
public CommandExecutor<T> executor() {
return executor;
}
public CommandContext<T> context() {
return context;
}
}
}

View file

@ -1,7 +1,6 @@
package de.kentoj.kencommandapi.internal.parser;
import de.kentoj.kencommandapi.api.literal.Literal;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
@ -9,11 +8,14 @@ import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
@RequiredArgsConstructor
public class SuggestionCommandParser<T> {
private final CommandParseHelper<T> helper;
public SuggestionCommandParser(CommandParseHelper<T> helper) {
this.helper = helper;
}
public List<String> suggest(
Literal<T> rootLiteral,
T sender,
@ -55,7 +57,7 @@ public class SuggestionCommandParser<T> {
T sender,
boolean suggestNext
) {
var argsIter = literal.getArguments().iterator();
var argsIter = literal.arguments().iterator();
/*
for each argument:
@ -72,16 +74,16 @@ public class SuggestionCommandParser<T> {
while (argsIter.hasNext()) {
var argument = argsIter.next();
if (!tokenIter.hasNext())
return argument.getSuggestionProvider().suggest(sender);
var input = helper.parseInput(tokenIter, argument.getType().isGreedy()).toLowerCase();
return argument.suggestionProvider().suggest(sender);
var input = helper.parseInput(tokenIter, argument.type().greedy()).toLowerCase();
if (tokenIter.hasNext())
continue;
if (suggestNext) {
if (argsIter.hasNext())
return argsIter.next().getSuggestionProvider().suggest(sender);
return argsIter.next().suggestionProvider().suggest(sender);
return null;
}
return argument.getSuggestionProvider().suggest(sender).stream()
return argument.suggestionProvider().suggest(sender).stream()
.filter(suggestion -> suggestion.toLowerCase().startsWith(input))
.toList();
}
@ -89,9 +91,9 @@ public class SuggestionCommandParser<T> {
}
private Stream<String> suggestions(Literal<T> literal, T sender) {
return literal.getLiterals().stream()
return literal.literals().stream()
.filter(lit -> helper.hasPermission(sender, lit))
.map(Literal::getNames)
.map(Literal::names)
.flatMap(Arrays::stream);
}
}

View file

@ -1,34 +0,0 @@
package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.Literal;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.stream.Stream;
public class BukkitKenCommand extends Command {
private final Literal<CommandSender> rootNode;
private final CommandHandler<CommandSender> commandHandler;
protected BukkitKenCommand(
CommandHandler<CommandSender> commandHandler,
Literal<CommandSender> rootLiteral
) {
super(rootLiteral.getNames()[0]);
this.commandHandler = commandHandler;
this.rootNode = rootLiteral;
this.setAliases(Arrays.asList(rootLiteral.getNames()));
this.setPermission(rootLiteral.getPermission());
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
commandHandler.invoke(rootNode, sender, Stream.of(args)
.filter(str -> !str.isEmpty()));
return true;
}
}

View file

@ -1,9 +0,0 @@
package de.kentoj.kencommandapi.api.argument;
import lombok.Value;
@Value
public class CommandArgumentImpl<T, V> implements CommandArgument<T, V> {
V value;
CommandArgumentSpec<T, V> argument;
}

View file

@ -1,42 +0,0 @@
package de.kentoj.kencommandapi.api.argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.Function;
@RequiredArgsConstructor
public final class CommandArgumentSpecImpl<T, V> implements CommandArgumentSpec<T, V> {
@Getter
private final String id;
@Getter
private final ArgumentType<T, V> type;
private final List<ArgumentRequirement<V>> requirements;
private final Function<CommandContext<T>, V> defaultValueProvider;
private final @Nullable SuggestionProvider<T> suggestionProvider;
@Override
public V parseInput(String rawInput) {
var parsed = type.parseInputUnchecked(rawInput);
for (var requirement : requirements) {
if (!requirement.getPredicate().test(parsed))
throw new IllegalArgumentException(requirement.getMessage());
}
return parsed;
}
@Override
public @Nullable Function<CommandContext<T>, V> getDefaultValueProvider() {
return defaultValueProvider;
}
@Override
public @NotNull SuggestionProvider<T> getSuggestionProvider() {
return suggestionProvider != null ? suggestionProvider : type.getDefaultSuggestionProvider();
}
}

View file

@ -1,38 +0,0 @@
package de.kentoj.kencommandapi.api.literal;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
public class LiteralImpl<T> implements Literal<T> {
private final String[] names;
private final List<Literal<T>> literals;
private final List<CommandArgumentSpec<T, ?>> arguments;
private final CommandExecutor<T> executor;
/**
* what the literal does
*/
private String description;
private final @Nullable String permission;
private final MessageStyle messageStyle;
@Override
public @Nullable Literal<T> getLiteral(@NotNull String name) {
for (Literal<T> literal : literals) {
for (var literalName : literal.getNames()) {
if (literalName.equalsIgnoreCase(name))
return literal;
}
}
return null;
}
}

View file

@ -1,25 +0,0 @@
package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.Literal;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
@RequiredArgsConstructor
public class CommandAPI {
private final ProxyServer server;
private final CommandHandler<CommandSource> commandHandler =
new CommandHandler<>(CommandSource::sendMessage, CommandSource::hasPermission);
public void register(Literal<CommandSource> rootNode) {
var cm = server.getCommandManager();
var meta = cm.metaBuilder(rootNode.getNames()[0])
.aliases(Arrays.copyOfRange(rootNode.getNames(), 1, rootNode.getNames().length))
.build();
cm.register(meta, new VelocityCommand(commandHandler, rootNode));
}
}

View file

@ -1,36 +0,0 @@
package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.RawCommand;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.Literal;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.List;
@RequiredArgsConstructor
public class VelocityCommand implements RawCommand {
private final CommandHandler<CommandSource> commandHandler;
private final Literal<CommandSource> rootNode;
@Override
public void execute(Invocation invocation) {
var args = Arrays.stream(invocation.arguments().split(" "))
.filter(a -> !a.isEmpty());
commandHandler.invoke(rootNode, invocation.source(), args);
}
@Override
public boolean hasPermission(Invocation ctx) {
if (rootNode.getPermission() == null) return true;
return ctx.source().hasPermission(rootNode.getPermission());
}
@Override
public List<String> suggest(Invocation invocation) {
var args = invocation.arguments().split(" ");
return commandHandler.getSuggestions(rootNode, invocation.source(), args, invocation.arguments().endsWith(" "));
}
}

7
third_party/BUILD vendored
View file

@ -1,7 +0,0 @@
load("@rules_java//java:java_plugin.bzl", "java_plugin")
java_plugin(
name = "lombok_plugin",
visibility = ["//visibility:public"],
deps = ["@maven//:org_projectlombok_lombok"],
processor_class = "lombok.launch.AnnotationProcessorHider$AnnotationProcessor",
)

View file

@ -1,24 +0,0 @@
[versions]
shadow = "9.2.0"
run-paper = "2.3.1"
papermc = "1.21.11-rc3-R0.1-SNAPSHOT"
velocity = "3.5.0-SNAPSHOT"
adventure = "5.2.0"
scrow-commandapi = "0.33-SNAPSHOT"
[plugins]
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
runpaper = { id = "xyz.jpenilla.run-paper", version.ref = "run-paper" }
scrow-basedependencies = { id = "scrow.base-dependencies" }
scrow-javalibrary = { id = "scrow.java-library" }
[libraries]
# https://docs.papermc.io/paper/dev/project-setup/
papermc-api = { module = "io.papermc.paper:paper-api", version.ref = "papermc" }
# https://docs.papermc.io/velocity/dev/creating-your-first-plugin/
velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" }
adventure-api = { module = "net.kyori:adventure-api", version.ref = "adventure" }
adventure-minimessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "adventure" }
# http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-core
scrow-commandapi-core = { module = "de.kentoj.scrow:kencommandapi-core", version.ref = "scrow-commandapi" }

View file

@ -5,14 +5,11 @@ java_export(
maven_coordinates = "de.kentoj.scrow:kencommandapi-velocity:0.34-SNAPSHOT",
srcs = glob(["src/main/**/*.java"]),
deps = [
"//kencommandapi-core:core",
artifact("org.projectlombok:lombok"),
"//core",
artifact("org.jetbrains:annotations"),
artifact("com.velocitypowered:velocity-api"),
],
exports = [
"//kencommandapi-core:core",
"//core",
],
plugins = [ "//third_party:lombok_plugin" ],
)

View file

@ -0,0 +1,28 @@
package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import java.util.Arrays;
public class CommandAPI<T extends CommandSource> {
private final ProxyServer server;
private final Class<T> senderType;
private final CommandHandler<T> commandHandler = new CommandHandler<>(T::sendMessage, T::hasPermission);
public CommandAPI(ProxyServer server, Class<T> senderType) {
this.server = server;
this.senderType = senderType;
}
public void register(RootLiteral<T> rootNode) {
var cm = server.getCommandManager();
var meta = cm.metaBuilder(rootNode.names()[0])
.aliases(Arrays.copyOfRange(rootNode.names(), 1, rootNode.names().length))
.build();
cm.register(meta, new VelocityCommand<>(commandHandler, rootNode, senderType));
}
}

View file

@ -0,0 +1,53 @@
package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.RawCommand;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class VelocityCommand<T extends CommandSource> implements RawCommand {
private final CommandHandler<T> commandHandler;
private final RootLiteral<T> rootNode;
private final Class<T> senderType;
public VelocityCommand(CommandHandler<T> commandHandler, RootLiteral<T> rootNode, Class<T> senderType) {
this.commandHandler = commandHandler;
this.rootNode = rootNode;
this.senderType = senderType;
}
@Override
public void execute(Invocation invocation) {
if (!senderType.isInstance(invocation.source())) {
invocation.source().sendMessage(MessageStyle.PLAIN.err("You can't use that command"));
return;
}
T sender = senderType.cast(invocation.source());
var args = Arrays.stream(invocation.arguments().split(" "))
.filter(a -> !a.isEmpty());
commandHandler.invoke(rootNode, sender, args);
}
@Override
public boolean hasPermission(Invocation ctx) {
if (rootNode.permission() == null) return true;
return ctx.source().hasPermission(rootNode.permission());
}
@Override
public List<String> suggest(Invocation invocation) {
if (!senderType.isInstance(invocation.source()))
return Collections.emptyList();
T sender = senderType.cast(invocation.source());
var args = invocation.arguments().split(" ");
return commandHandler.getSuggestions(rootNode, sender, args, invocation.arguments().endsWith(" "));
}
}

View file

@ -4,16 +4,17 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import lombok.RequiredArgsConstructor;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSource> {
public final class PlayerSuggestionProvider implements SuggestionProvider<CommandSource> {
private final ProxyServer proxyServer;
public PlayerSuggestionProvider(ProxyServer proxyServer) {
this.proxyServer = proxyServer;
}
@Override
public List<String> suggest(CommandSource __) {
return proxyServer.getAllPlayers().stream()

View file

@ -6,13 +6,15 @@ import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import de.kentoj.kencommandapi.suggestionprovider.PlayerSuggestionProvider;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class PlayerArgumentType implements ArgumentType<CommandSource, Player> {
private final ProxyServer server;
public PlayerArgumentType(ProxyServer server) {
this.server = server;
}
@Override
public Player parseInputUnchecked(String input) {
var player = server.getPlayer(input).orElse(null);