currently refactoring a lot.

This commit is contained in:
kento2 2026-07-04 01:04:01 +02:00
parent fe0b04c7d1
commit 9aa138058c
32 changed files with 484 additions and 254 deletions

1
.idea/vcs.xml generated
View file

@ -2,5 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../build-logic" vcs="Git" />
</component>
</project>

205
.idea/workspace.xml generated
View file

@ -5,57 +5,41 @@
</component>
<component name="ChangeListManager">
<list default="true" id="6414223f-1761-4683-97f5-9dab59d6c44a" name="Changes" comment=".">
<change afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/build.gradle.kts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/CommandNode.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandContext.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandExecutor.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/Result.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandArgumentImpl.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/ParsedArgumentImpl.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/CommandParser.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/ParseResult.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/PermissionChecker.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/de/kentoj/scrow/ReactorConvention.kt" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/AsyncTabCompleter.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/CommandHandler.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/node/RootCommandNode.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/MessageStyle.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/PlainMessageStyle.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/SendMessageMethod.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/RootCommandNodeImpl.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-bukkit/build.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitCommandContext.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommand.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommand.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommandApi.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/suggestionprovider/PlayerSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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$/kencommandapi-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$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/type/PlayerArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/Main.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/KenCommandApi.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/argument/ArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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$/kencommandapi-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/SuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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/api/argument/suggestion/NoSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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/nodes/ArgumentNode.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/nodes/CommandNode.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/nodes/LiteralNode.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/processing/CommandContext.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/processing/CommandException.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/processing/CommandExecutor.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/processing/ParsedArgument.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/ParsedArgument.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/types/IntegerArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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/types/StringArgumentType.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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/impl/AbstractKenCommandApi.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/impl/processing/CommandContextImpl.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/impl/processing/ParsedArgumentImpl.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/impl/processing/TabCompleter.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/impl/structure/CommandArgumentImpl.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/impl/structure/CommandNodeImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandNodeImpl.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-velocity/build.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/build.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/CommandNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/node/CommandNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/invocation/CommandExecutor.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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/Result.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/suggestion/NoSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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$/kencommandapi-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/CommandArgumentImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandArgumentImpl.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandNodeImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandNodeImpl.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/CommandParser.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser/CommandParser.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/ParseResult.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser/ParseResult.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/parser/PermissionChecker.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/HasPermissionMethod.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommand.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommand.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommandContext.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityKenCommandApi.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/suggestionprovider/PlayerSuggestionProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-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$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/type/PlayerArgumentType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/settings.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/settings.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../build-logic/convention/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/convention/build.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/de/kentoj/scrow/BaseDependenciesConvention.kt" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/de/kentoj/scrow/BaseDependenciesConvention.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/de/kentoj/scrow/ScrowRepositoryConvention.kt" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/de/kentoj/scrow/ScrowRepositoryConvention.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../build-logic/settings.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/settings.gradle.kts" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -92,17 +76,25 @@
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="KenCommandAPI" type="f1a62948:ProjectNode" />
<item name="KenCommandAPI" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="KenCommandAPI" type="f1a62948:ProjectNode" />
<item name="KenCommandAPI" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="KenCommandAPI" type="f1a62948:ProjectNode" />
<item name="KenCommandAPI" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="build" type="c8890929:TasksNode$1" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="KenCommandAPI" type="f1a62948:ProjectNode" />
<item name="KenCommandAPI" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="publishing" type="c8890929:TasksNode$1" />
</path>
@ -125,6 +117,9 @@
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="GradleScriptDefinitionsStorage" workingDir="$PROJECT_DIR$" gradleHome="$USER_HOME$/.gradle/wrapper/dists/gradle-8.14-bin/38aieal9i53h9rfe7vjup95b9/gradle-8.14" javaHome="/usr/lib/jvm/default-jdk" gradleVersion="8.14" />
<component name="HighlightingSettingsPerFile">
<setting file="jrt:///usr/lib/jvm/openjdk21!/java.base/java/util/function/Function.class" root0="SKIP_INSPECTION" />
</component>
<component name="ProblemsViewState">
<option name="selectedTabId" value="CurrentFile" />
</component>
@ -139,38 +134,40 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"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",
"Gradle.KenCommandAPI [:de.kencommand.Main.main()].executor": "Run",
"Gradle.KenCommandAPI [assemble].executor": "Run",
"Gradle.KenCommandAPI [build].executor": "Run",
"Gradle.KenCommandAPI [clean].executor": "Run",
"Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository].executor": "Run",
"Gradle.KenCommandAPI [publish].executor": "Run",
"Gradle.KenCommandAPI:kencommandapi-bukkit [build].executor": "Run",
"Gradle.KenCommandAPI:kencommandapi-bukkit [generatePomFileForKenCommandAPIBukkitPublication].executor": "Run",
"Gradle.KenCommandAPI:kencommandapi-bukkit [publishAllPublicationsToScrowRepository].executor": "Run",
"Gradle.KenCommandAPI:kencommandapi-bukkit [publish].executor": "Run",
"Gradle.KenCommandAPI:kencommandapi-velocity [publish].executor": "Run",
"Gradle.kencommandapi-core [build].executor": "Run",
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "master",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "/home/a/src/scrow/KenCommandAPI/kencommandapi-core",
"project.structure.last.edited": "Modules",
"project.structure.proportion": "0.15",
"project.structure.side.proportion": "0.6268199",
"settings.editor.selected.configurable": "configurable.group.appearance"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [:kencommandapi-core:de.kentoj.kencommandapi.Main.main()].executor&quot;: &quot;Run&quot;,
&quot;Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [build].executor&quot;: &quot;Run&quot;,
&quot;Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [publish].executor&quot;: &quot;Run&quot;,
&quot;Gradle.Download Sources.executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI [:de.kencommand.Main.main()].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI [assemble].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI [build].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI [clean].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI [publish].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI:kencommandapi-bukkit [build].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI:kencommandapi-bukkit [generatePomFileForKenCommandAPIBukkitPublication].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI:kencommandapi-bukkit [publishAllPublicationsToScrowRepository].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI:kencommandapi-bukkit [publish].executor&quot;: &quot;Run&quot;,
&quot;Gradle.KenCommandAPI:kencommandapi-velocity [publish].executor&quot;: &quot;Run&quot;,
&quot;Gradle.kencommandapi-core [build].executor&quot;: &quot;Run&quot;,
&quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master&quot;,
&quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/a/src/scrow/KenCommandAPI/kencommandapi-core&quot;,
&quot;project.structure.last.edited&quot;: &quot;Modules&quot;,
&quot;project.structure.proportion&quot;: &quot;0.15&quot;,
&quot;project.structure.side.proportion&quot;: &quot;0.6268199&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;
}
}]]></component>
}</component>
<component name="RecentsManager">
<key name="CreateClassDialog.RecentsKey">
<recent name="de.kentoj.kencommandapi.api" />
<recent name="de.kentoj.kencommandapi.api.invocation" />
<recent name="de.kencommand.api.structure.argument" />
<recent name="de.kencommand.api.structure" />
@ -185,40 +182,20 @@
<recent name="$PROJECT_DIR$/kencommandapi-core" />
</key>
<key name="CopyClassDialog.RECENTS_KEY">
<recent name="de.kentoj.kencommandapi.internal" />
<recent name="de.kentoj.kencommandapi.api" />
<recent name="de.kentoj.kencommandapi.impl" />
<recent name="de.kentoj.kencommandapi.api.structure.argument.types" />
<recent name="de.kentoj.kencommandapi.type" />
<recent name="de.kencommand.api" />
</key>
</component>
<component name="RunAnythingCache">
<option name="myCommands">
<command value="publishAll" />
<command value="KenCommandAPI [publishAllPublicationsToScrowRepository]" />
</option>
</component>
<component name="RunManager" selected="Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository]">
<configuration name="KenCommandAPI [assemble]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="assemble" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration name="KenCommandAPI [build]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
@ -241,6 +218,28 @@
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration name="KenCommandAPI [clean]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="clean" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration name="KenCommandAPI [publishAllPublicationsToScrowRepository]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
@ -311,9 +310,9 @@
<list>
<item itemvalue="Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository]" />
<item itemvalue="Gradle.KenCommandAPI [build]" />
<item itemvalue="Gradle.KenCommandAPI [publish]" />
<item itemvalue="Gradle.KenCommandAPI [assemble]" />
<item itemvalue="Gradle.KenCommandAPI [clean]" />
<item itemvalue="Gradle.KenCommandAPI:kencommandapi-velocity [publish]" />
<item itemvalue="Gradle.KenCommandAPI [publish]" />
</list>
</recent_temporary>
</component>
@ -533,7 +532,23 @@
<option name="project" value="LOCAL" />
<updated>1780445840891</updated>
</task>
<option name="localTasksCounter" value="27" />
<task id="LOCAL-00027" summary=".">
<option name="closed" value="true" />
<created>1782751783492</created>
<option name="number" value="00027" />
<option name="presentableId" value="LOCAL-00027" />
<option name="project" value="LOCAL" />
<updated>1782751783492</updated>
</task>
<task id="LOCAL-00028" summary=".">
<option name="closed" value="true" />
<created>1782751797787</created>
<option name="number" value="00028" />
<option name="presentableId" value="LOCAL-00028" />
<option name="project" value="LOCAL" />
<updated>1782751797787</updated>
</task>
<option name="localTasksCounter" value="29" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">

View file

@ -1,8 +1,7 @@
group = "de.kentoj.scrow"
version = "0.10"
version = "0.21"
subprojects {
group = rootProject.group
version = rootProject.version
}

View file

@ -7,14 +7,14 @@ plugins {
}
repositories {
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
name = "spigotmc-repo"
maven("https://repo.papermc.io/repository/maven-public/") {
name = "papermc"
}
}
dependencies {
api(project(":kencommandapi-core"))
compileOnly("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.11-rc3-R0.1-SNAPSHOT")
}
publishing {

View file

@ -0,0 +1,25 @@
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;
@RequiredArgsConstructor
public class AsyncTabCompleter implements Listener {
private final CommandAPI commandAPI;
private final CommandHandler<CommandSender> commandHandler;
@EventHandler(ignoreCancelled = true)
public void onAsyncTabComplete(AsyncTabCompleteEvent ev) {
var args = ev.getBuffer().split(" ");
var label = args[0];
var rootNode = commandAPI.getRegistered(label);
if (rootNode == null) return;
commandHandler.getSuggestions(rootNode, ev.getSender(), args)
.thenAccept(ev::setCompletions);
}
}

View file

@ -1,9 +1,7 @@
package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.CommandNode;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.internal.parser.CommandParser;
import de.kentoj.kencommandapi.internal.parser.ParseResult;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
@ -12,15 +10,15 @@ import java.util.Arrays;
public class BukkitKenCommand extends Command {
private final CommandNode<CommandSender> rootNode;
private final CommandParser<CommandSender> commandParser;
private final RootCommandNode<CommandSender> rootNode;
private final CommandHandler<CommandSender> commandHandler;
protected BukkitKenCommand(
CommandParser<CommandSender> commandParser,
CommandNode<CommandSender> rootNode
CommandHandler<CommandSender> commandHandler,
RootCommandNode<CommandSender> rootNode
) {
super(rootNode.getNames()[0]);
this.commandParser = commandParser;
this.commandHandler = commandHandler;
this.rootNode = rootNode;
this.setAliases(Arrays.asList(rootNode.getNames()));
this.setPermission(rootNode.getPermission());
@ -28,21 +26,7 @@ public class BukkitKenCommand extends Command {
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
var parseResult = commandParser.parseLiteral(rootNode, sender, args);
if (parseResult instanceof ParseResult.Success<CommandSender>) {
var ctx = new CommandContext<>(sender, ((ParseResult.Success<CommandSender>) parseResult).getParsedArguments());
assert parseResult.getLiteral().getExecutor() != null;
try {
var result = parseResult.getLiteral().getExecutor().execute(ctx);
if (result.isError()) {
sender.sendMessage("§c" + result.getError());
}
} catch (Exception e) {
sender.sendMessage("§4§lERROR " + e.getMessage());
}
} else {
sender.sendMessage("§c" + parseResult.getMessage());
}
commandHandler.invoke(rootNode, sender, args);
return true;
}
}

View file

@ -1,27 +1,50 @@
package de.kentoj.kencommandapi;
import de.kentoj.kencommandapi.api.CommandNode;
import de.kentoj.kencommandapi.internal.parser.CommandParser;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import de.kentoj.kencommandapi.api.parser.CommandParser;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.permissions.Permissible;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class CommandAPI {
private final CommandParser<CommandSender> commandParser = new CommandParser<>(Permissible::hasPermission);
private final CommandHandler<CommandSender> commandHandler;
private final List<RootCommandNode<CommandSender>> registeredNodes = new ArrayList<>();
private final SimpleCommandMap commandMap;
public CommandAPI(Plugin plugin) {
this.commandHandler = new CommandHandler<>(new CommandParser<>(Permissible::hasPermission),
CommandSender::sendMessage, Permissible::hasPermission);
Bukkit.getPluginManager().registerEvents(new AsyncTabCompleter(this, commandHandler), plugin);
public void register(CommandNode<CommandSender> rootNode) {
SimpleCommandMap commandMap;
try {
Field field = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
field.setAccessible(true);
commandMap = (SimpleCommandMap) field.get(Bukkit.getPluginManager());
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalStateException("failed registering command ", e);
throw new IllegalStateException("failed getting command map", e);
}
commandMap.register(rootNode.getNames()[0], new BukkitKenCommand(commandParser, rootNode));
}
@Nullable RootCommandNode<CommandSender> getRegistered(String name) {
for (var node : registeredNodes) {
for (String nodeName : node.getNames()) {
if (nodeName.equals(name)) return node;
}
}
return null;
}
public void register(RootCommandNode<CommandSender> rootNode) {
registeredNodes.add(rootNode);
commandMap.register(rootNode.getNames()[0], new BukkitKenCommand(commandHandler, rootNode));
}
}

View file

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

View file

@ -26,10 +26,10 @@ public class OfflinePlayerArgumentType implements ArgumentType<CommandSender, Of
try {
player = Bukkit.getOfflinePlayer(UUID.fromString(string));
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Not a UUID or online player -- " + string);
throw new IllegalArgumentException("not an UUID or online player");
}
}
if (!player.hasPlayedBefore() && !player.isOnline()) throw new IllegalArgumentException("Unknown player -- " + string);
if (!player.hasPlayedBefore() && !player.isOnline()) throw new IllegalArgumentException("Player not found");
return player;
}

View file

@ -19,7 +19,7 @@ public class PlayerArgumentType implements ArgumentType<CommandSender, Player> {
@Override
public Player parseInput(String string) {
var player = Bukkit.getPlayer(string);
if (player == null) throw new IllegalArgumentException("Player not online -- " + string);
if (player == null) throw new IllegalArgumentException("player not online");
return player;
}

View file

@ -6,6 +6,14 @@ plugins {
id("de.kentoj.scrow.java-library")
}
repositories {
mavenCentral()
}
dependencies {
api("net.kyori:adventure-api:5.2.0")
}
publishing {
publications {
create<MavenPublication>("KenCommandAPI") {

View file

@ -0,0 +1,69 @@
package de.kentoj.kencommandapi.api;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.node.CommandNode;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import de.kentoj.kencommandapi.api.parser.CommandParser;
import de.kentoj.kencommandapi.api.parser.ParseResult;
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
import de.kentoj.kencommandapi.api.platform.SendMessageMethod;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
public class CommandHandler<T> {
private final CommandParser<T> commandParser;
private final SendMessageMethod<T> sendMessageMethod;
private final HasPermissionMethod<T> hasPermissionMethod;
public void invoke(RootCommandNode<T> rootNode, T sender, String[] args) {
var parseResult = commandParser.parseLiteral(rootNode, sender, args, true);
if (!(parseResult instanceof ParseResult.Success<T>)) {
sendMessageMethod.send(sender, rootNode.getMessageStyle().err(parseResult.getMessage()));
return;
}
var ctx = new CommandContext<>(sender, ((ParseResult.Success<T>) parseResult).getParsedArguments());
assert parseResult.getLiteral().getExecutor() != null;
parseResult.getLiteral().getExecutor().execute(ctx).whenComplete((result, ex) -> {
if (ex != null) {
sendMessageMethod.send(sender, rootNode.getMessageStyle().exception(ex));
}
result.ifFailure(failure ->
sendMessageMethod.send(sender, rootNode.getMessageStyle().err(failure))
);
});
}
public CompletableFuture<List<String>> getSuggestions(RootCommandNode<T> rootNode, T sender, String[] args) {
var parseResult = commandParser.parseLiteral(rootNode, sender, args, false);
if (parseResult instanceof ParseResult.ArgumentExpected<T>) {
var arg = ((ParseResult.ArgumentExpected<T>) parseResult).getArgument();
return arg.getSuggestionProvider().suggest(sender);
}
String filter = null;
if (parseResult instanceof ParseResult.UnknownLiteral<T>)
filter = ((ParseResult.UnknownLiteral<T>) parseResult).getName();
else if (parseResult instanceof ParseResult.NoPermission<T>)
filter = ((ParseResult.NoPermission<T>) parseResult).getName();
return getSuggestions(sender, parseResult.getLiteral(), filter);
}
private CompletableFuture<List<String>> getSuggestions(T sender, CommandNode<T> literal, @Nullable String filter) {
var stream = literal.getLiterals().stream()
.filter(lit -> lit.getPermission() != null && hasPermissionMethod.hasPermission(sender, lit.getPermission()))
.map(CommandNode::getNames)
.flatMap(Arrays::stream);
if (filter != null)
stream = stream.filter(f -> f.toLowerCase().contains(filter.toLowerCase()));
return CompletableFuture.completedFuture(stream.toList());
}
}

View file

@ -1,6 +1,10 @@
package de.kentoj.kencommandapi.api.invocation;
import com.leakyabstractions.result.api.Result;
import java.util.concurrent.CompletableFuture;
public interface CommandExecutor<T> {
Result execute(CommandContext<T> ctx);
CompletableFuture<Result<Void, String>> execute(CommandContext<T> ctx);
}

View file

@ -1,24 +0,0 @@
package de.kentoj.kencommandapi.api.invocation;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
@RequiredArgsConstructor
@Getter
public class Result {
public static Result success() {
return new Result(null);
}
public static Result error(String error) {
return new Result(error);
}
private final @Nullable String error;
public boolean isError() {
return error != null;
}
}

View file

@ -1,8 +1,10 @@
package de.kentoj.kencommandapi.api;
package de.kentoj.kencommandapi.api.node;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.internal.CommandNodeImpl;
import de.kentoj.kencommandapi.internal.RootCommandNodeImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -14,6 +16,10 @@ public interface CommandNode<T> {
return new CommandNodeImpl<>(name);
}
static <T> RootCommandNode<T> rootNode(MessageStyle messageStyle, String...name) {
return new RootCommandNodeImpl<>(messageStyle, name);
}
@NotNull String[] getNames();
void setDescription(@Nullable String description);

View file

@ -0,0 +1,10 @@
package de.kentoj.kencommandapi.api.node;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
public interface RootCommandNode<T> extends CommandNode<T> {
MessageStyle getMessageStyle();
void setMessageStyle(MessageStyle messageStyle);
}

View file

@ -1,8 +1,12 @@
package de.kentoj.kencommandapi.internal.parser;
package de.kentoj.kencommandapi.api.parser;
import de.kentoj.kencommandapi.api.CommandNode;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
import de.kentoj.kencommandapi.api.node.CommandNode;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import de.kentoj.kencommandapi.internal.ParsedArgumentImpl;
import lombok.RequiredArgsConstructor;
@ -14,28 +18,25 @@ import java.util.Map;
@RequiredArgsConstructor
public class CommandParser<T> {
private final PermissionChecker<T> hasPermissionMethod;
private final HasPermissionMethod<T> hasPermissionMethod;
public ParseResult<T> parseLiteral(CommandNode<T> rootNode, T sender, String[] args) {
var cur = rootNode;
public ParseResult<T> parseLiteral(RootCommandNode<T> rootNode, T sender, String[] args, boolean parseArgs) {
CommandNode<T> cur = rootNode;
final Iterator<String> argStrIter = Arrays.stream(args).iterator();
final Map<String, ParsedArgument<T, ?>> parsedArguments = new HashMap<>();
while (argStrIter.hasNext()) {
for (var nodeArg : cur.getArguments()) {
ParsedArgument<T, Object> parsed;
try {
parsed = parseArgument(argStrIter, sender, nodeArg);
} catch (IllegalArgumentException ex) {
return new ParseResult.IllegalArgument<>(cur, ex.getMessage());
}
if (parsed == null) return new ParseResult.IncompleteArgument<>(cur, nodeArg);
parsedArguments.put(nodeArg.getId(), parsed);
var parsed = parseArgument(rootNode, nodeArg, argStrIter, sender, !parseArgs);
if (parsed.hasFailure())
return parsed.getFailure().orElseThrow();
if (parseArgs)
parsedArguments.put(nodeArg.getId(), parsed.getSuccess().orElseThrow());
}
if (!argStrIter.hasNext()) {
if (cur.getExecutor() == null)
return new ParseResult.IncompleteCommand<>(cur);
return new ParseResult.LiteralExpected<>(cur);
return new ParseResult.Success<>(cur, parsedArguments);
}
@ -48,23 +49,40 @@ public class CommandParser<T> {
cur = nextNode;
}
throw new RuntimeException("code reached unexpected line");
if (cur.getExecutor() == null)
return new ParseResult.LiteralExpected<>(cur);
return new ParseResult.Success<>(cur, parsedArguments);
}
@SuppressWarnings("unchecked")
private ParsedArgument<T, Object> parseArgument(Iterator<String> args, T sender, CommandArgument<T, ?> nodeArg) {
private Result<ParsedArgument<T, Object>, ParseResult<T>> parseArgument(
CommandNode<T> node,
CommandArgument<T, ?> nodeArg,
Iterator<String> args,
T sender,
boolean fakeParse
) {
Object value;
if (args.hasNext()) {
var argStr = getRawArgument(args, nodeArg);
if (fakeParse) {
value = null;
} else {
try {
value = nodeArg.getType().parseInput(argStr);
} catch (IllegalArgumentException ex) {
return Results.failure(new ParseResult.IllegalArgument<>(node, nodeArg, ex.getMessage(), argStr));
}
}
} else {
if (nodeArg.getDefaultValueProvider() == null)
return null;
return Results.failure(new ParseResult.ArgumentExpected<>(node, nodeArg));
value = nodeArg.getDefaultValueProvider().apply(sender);
}
return new ParsedArgumentImpl<>(value, (CommandArgument<T, Object>) nodeArg);
var parsedArg = new ParsedArgumentImpl<>(value, (CommandArgument<T, Object>) nodeArg);
return Results.success(parsedArg);
}
private String getRawArgument(Iterator<String> args, CommandArgument<T, ?> arg) {

View file

@ -1,15 +1,15 @@
package de.kentoj.kencommandapi.internal.parser;
package de.kentoj.kencommandapi.api.parser;
import de.kentoj.kencommandapi.api.CommandNode;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
import de.kentoj.kencommandapi.api.node.CommandNode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Map;
public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument, ParseResult.IncompleteArgument,
ParseResult.IncompleteCommand, ParseResult.NoPermission, ParseResult.Success, ParseResult.UnknownLiteral {
public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument, ParseResult.ArgumentExpected,
ParseResult.LiteralExpected, ParseResult.NoPermission, ParseResult.Success, ParseResult.UnknownLiteral {
/**
* @return last successfully literal
@ -19,25 +19,27 @@ public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument,
public abstract String getMessage();
@RequiredArgsConstructor
public static final class IncompleteArgument<T> extends ParseResult<T> {
public static final class ArgumentExpected<T> extends ParseResult<T> {
@Getter
private final CommandNode<T> literal;
@Getter
private final CommandArgument<T, ?> argument;
@Override
public String getMessage() {
return "Missing value for argument: " + argument.getId();
return "Argument expected: " + argument.getId();
}
}
@RequiredArgsConstructor
public static final class UnknownLiteral<T> extends ParseResult<T> {
private final CommandNode<T> previousLiteral;
@Getter
private final String name;
@Override
public String getMessage() {
return "Unknown literal: " + name;
return "Unknown subcommand: " + name;
}
@Override
@ -47,13 +49,13 @@ public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument,
}
@RequiredArgsConstructor
public static final class IncompleteCommand<T> extends ParseResult<T> {
public static final class LiteralExpected<T> extends ParseResult<T> {
@Getter
private final CommandNode<T> literal;
@Override
public String getMessage() {
return "Incomplete command";
return "Subcommand expected";
}
}
@ -74,11 +76,12 @@ public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument,
public static final class NoPermission<T> extends ParseResult<T> {
@Getter
private final CommandNode<T> literal;
@Getter
private final String name;
@Override
public String getMessage() {
return "Unknown literal: " + name;
return "Unknown subcommand: " + name;
}
}
@ -86,7 +89,26 @@ public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument,
public static final class IllegalArgument<T> extends ParseResult<T> {
@Getter
private final CommandNode<T> literal;
@Getter
private final CommandArgument<T, ?> argument;
private final String message;
/**
* Input passed to the parser
*/
@Getter
private final String argStr;
public IllegalArgument(CommandNode<T> literal, CommandArgument<T, ?> argument, Throwable throwable, String argStr) {
this.literal = literal;
this.argument = argument;
this.argStr = argStr;
while (throwable.getMessage() == null && throwable.getCause() != null)
throwable = throwable.getCause();
message = throwable.getMessage();
}
@Override
public String getMessage() {
return "Illegal argument '" + argStr + "' for " + argument.getId() + ":" + message;
}
}
}

View file

@ -0,0 +1,6 @@
package de.kentoj.kencommandapi.api.platform;
@FunctionalInterface
public interface HasPermissionMethod<T> {
boolean hasPermission(T sender, String permission);
}

View file

@ -0,0 +1,32 @@
package de.kentoj.kencommandapi.api.platform;
import net.kyori.adventure.text.Component;
public interface MessageStyle {
MessageStyle PLAIN = new PlainMessageStyle();
Component ok(Component msg);
Component err(Component msg);
Component exception(Component msg);
default Component ok(String msg) {
return ok(Component.text(msg));
}
default Component err(String msg) {
return err(Component.text(msg));
}
default Component exception(String msg) {
return exception(Component.text(msg));
}
default Component exception(Throwable ex) {
while (ex.getMessage() == null && ex.getCause() != null)
ex = ex.getCause();
return exception(ex.getMessage());
}
}

View file

@ -0,0 +1,20 @@
package de.kentoj.kencommandapi.api.platform;
import net.kyori.adventure.text.Component;
public class PlainMessageStyle implements MessageStyle {
@Override
public Component ok(Component msg) {
return msg;
}
@Override
public Component err(Component msg) {
return msg;
}
@Override
public Component exception(Component msg) {
return Component.text("ERROR: ").append(msg);
}
}

View file

@ -0,0 +1,8 @@
package de.kentoj.kencommandapi.api.platform;
import net.kyori.adventure.text.Component;
@FunctionalInterface
public interface SendMessageMethod<T> {
void send(T to, Component msg);
}

View file

@ -1,15 +1,13 @@
package de.kentoj.kencommandapi.api.suggestion;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import java.util.Collections;
import java.util.Set;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class NoSuggestionProvider<T> implements SuggestionProvider<T> {
@Override
public CompletableFuture<Set<String>> suggest(CommandContext<T> __) {
return CompletableFuture.completedFuture(Collections.emptySet());
public CompletableFuture<List<String>> suggest(T __) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
}

View file

@ -1,11 +1,12 @@
package de.kentoj.kencommandapi.api.suggestion;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import java.util.Set;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public interface SuggestionProvider<T> {
CompletableFuture<Set<String>> suggest(CommandContext<T> context);
/**
* @return an unfiltered(no permission checks or filtering by input) list of strings that may be used for the argument
*/
CompletableFuture<List<String>> suggest(T sender);
}

View file

@ -6,6 +6,7 @@ import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
@ -22,7 +23,13 @@ public class CommandArgumentImpl<T, V> implements CommandArgument<T, V> {
@Setter
private @Nullable Function<T, V> defaultValueProvider;
@Getter
@Setter
private @Nullable SuggestionProvider<T> suggestionProvider;
@Override
public @NotNull SuggestionProvider<T> getSuggestionProvider() {
if (suggestionProvider == null)
return getType().defaultSuggestionProvider();
return this.suggestionProvider;
}
}

View file

@ -1,6 +1,6 @@
package de.kentoj.kencommandapi.internal;
import de.kentoj.kencommandapi.api.CommandNode;
import de.kentoj.kencommandapi.api.node.CommandNode;
import de.kentoj.kencommandapi.api.argument.CommandArgument;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import lombok.Getter;
@ -65,6 +65,7 @@ public class CommandNodeImpl<T> implements CommandNode<T> {
}
private boolean isGreedy() {
if (arguments.isEmpty()) return false;
var arg = arguments.getLast();
return arg != null && arg.getType().isGreedy();
}

View file

@ -0,0 +1,17 @@
package de.kentoj.kencommandapi.internal;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import lombok.Getter;
import lombok.Setter;
public class RootCommandNodeImpl<T> extends CommandNodeImpl<T> implements RootCommandNode<T> {
@Setter
@Getter
private MessageStyle messageStyle;
public RootCommandNodeImpl(MessageStyle messageStyle, String[] names) {
super(names);
this.messageStyle = messageStyle;
}
}

View file

@ -1,6 +0,0 @@
package de.kentoj.kencommandapi.internal.parser;
@FunctionalInterface
public interface PermissionChecker<T> {
boolean hasPermission(T sender, String permission);
}

View file

@ -2,8 +2,9 @@ package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.CommandNode;
import de.kentoj.kencommandapi.internal.parser.CommandParser;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import de.kentoj.kencommandapi.api.parser.CommandParser;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
@ -12,13 +13,17 @@ import java.util.Arrays;
public class CommandAPI {
private final ProxyServer server;
private final CommandParser<CommandSource> commandParser = new CommandParser<>(CommandSource::hasPermission);
private final CommandHandler<CommandSource> commandHandler = new CommandHandler<>(
new CommandParser<>(CommandSource::hasPermission),
CommandSource::sendMessage,
CommandSource::hasPermission
);
public void register(CommandNode<CommandSource> rootNode) {
public void register(RootCommandNode<CommandSource> rootNode) {
var cm = server.getCommandManager();
var meta = cm.metaBuilder(rootNode.getNames()[0])
.aliases(Arrays.copyOfRange(rootNode.getNames(), 1, rootNode.getNames().length - 1))
.build();
cm.register(meta, new VelocityCommand(commandParser, rootNode));
cm.register(meta, new VelocityCommand(commandHandler, rootNode));
}
}

View file

@ -2,42 +2,22 @@ package de.kentoj.kencommandapi;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand;
import de.kentoj.kencommandapi.api.CommandNode;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.internal.parser.CommandParser;
import de.kentoj.kencommandapi.internal.parser.ParseResult;
import de.kentoj.kencommandapi.api.CommandHandler;
import de.kentoj.kencommandapi.api.node.RootCommandNode;
import lombok.RequiredArgsConstructor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
public class VelocityCommand implements SimpleCommand {
private final CommandParser<CommandSource> commandParser;
private final CommandNode<CommandSource> rootNode;
private final CommandHandler<CommandSource> commandHandler;
private final RootCommandNode<CommandSource> rootNode;
@Override
public void execute(Invocation invocation) {
var parseResult = commandParser.parseLiteral(rootNode, invocation.source(), invocation.arguments());
if (parseResult instanceof ParseResult.Success<CommandSource>) {
var ctx = new CommandContext<>(invocation.source(), ((ParseResult.Success<CommandSource>) parseResult).getParsedArguments());
assert parseResult.getLiteral().getExecutor() != null;
try {
var result = parseResult.getLiteral().getExecutor().execute(ctx);
if (result.getError() != null)
invocation.source().sendMessage(Component.text(result.getError()).color(NamedTextColor.RED));
} catch (Exception e) {
invocation.source().sendMessage(Component.text("ERROR ")
.append(Component.text(e.getMessage()))
.color(NamedTextColor.DARK_RED)
.decorate(TextDecoration.BOLD));
}
} else {
invocation.source().sendMessage(Component.text(parseResult.getMessage()).color(NamedTextColor.RED));
}
commandHandler.invoke(rootNode, invocation.source(), invocation.arguments());
}
@Override
@ -45,4 +25,9 @@ public class VelocityCommand implements SimpleCommand {
if (rootNode.getPermission() == null) return true;
return ctx.source().hasPermission(rootNode.getPermission());
}
@Override
public CompletableFuture<List<String>> suggestAsync(Invocation invocation) {
return commandHandler.getSuggestions(rootNode, invocation.source(), invocation.arguments());
}
}

View file

@ -3,13 +3,11 @@ 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.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import lombok.RequiredArgsConstructor;
import java.util.Set;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class PlayerSuggestionProvider implements SuggestionProvider<CommandSource> {
@ -17,10 +15,10 @@ public class PlayerSuggestionProvider implements SuggestionProvider<CommandSourc
private final ProxyServer proxyServer;
@Override
public CompletableFuture<Set<String>> suggest(CommandContext<CommandSource> context) {
public CompletableFuture<List<String>> suggest(CommandSource __) {
var list = proxyServer.getAllPlayers().stream()
.map(Player::getUsername)
.collect(Collectors.toSet());
.toList();
return CompletableFuture.completedFuture(list);
}
}

View file

@ -16,7 +16,7 @@ public class PlayerArgumentType implements ArgumentType<CommandSource, Player> {
@Override
public Player parseInput(String string) {
var player = server.getPlayer(string).orElse(null);
if (player == null) throw new IllegalArgumentException("Player not online -- " + string);
if (player == null) throw new IllegalArgumentException("Player not online");
return player;
}