Skip to content

Commit

Permalink
fix(arguments): list argument not working properly
Browse files Browse the repository at this point in the history
  • Loading branch information
StillLutto committed Dec 16, 2024
1 parent 724f020 commit 91ad273
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ import com.undefined.stellar.argument.types.text.ComponentArgument
import com.undefined.stellar.argument.types.text.MessageArgument
import com.undefined.stellar.argument.types.text.StyleArgument
import com.undefined.stellar.argument.types.world.*
import com.undefined.stellar.data.suggestion.Suggestion
import org.bukkit.Bukkit
import org.bukkit.OfflinePlayer
import org.bukkit.entity.Player
import java.util.*

@Suppress("DEPRECATION")
open class ArgumentHandler {

open val base: AbstractStellarCommand<*> get() = throw IllegalStateException("Cannot access the getter from the property base when it hasn't been overridden!")
Expand Down Expand Up @@ -77,28 +79,30 @@ open class ArgumentHandler {
fun addBooleanArgument(name: String): BooleanArgument =
addArgument { BooleanArgument(base, name) }

fun <T> addListArgument(
name: String,
fun <T, U : AbstractStellarArgument<*>> addListArgument(
type: AbstractStellarArgument<*>,
list: List<T>,
stringifier: (T) -> String,
parse: (String) -> T,
type: AbstractStellarArgument<*> = StringArgument(base, name, StringType.WORD)
): ListArgument<T> = addArgument { ListArgument(base, name, list, stringifier, parse, type) }
stringifier: (T) -> Suggestion,
parse: (Any?) -> T
): ListArgument<T> = addArgument { ListArgument(base, type, list, stringifier, parse) }

fun addStringListArgument(name: String, list: List<String>, type: StringType = StringType.WORD): ListArgument<String> =
addArgument { ListArgument(base, StringArgument(base, name, type), list, { Suggestion.withText(it.toString()) }, { it }) }

fun addStringListArgument(name: String, list: List<String>, type: StringType): ListArgument<String> =
addArgument { ListArgument(base, name, list, { it }, { it }, StringArgument(base, name, type)) }
fun addStringListArgument(name: String, vararg list: String): ListArgument<String> =
addArgument { ListArgument(base, StringArgument(base, name, StringType.WORD), list.toList(), { Suggestion.withText(it.toString()) }, { it }) }

fun addUUIDListArgument(name: String, list: List<UUID>): ListArgument<UUID> =
addArgument { ListArgument(base, name, list, parse = { UUID.fromString(it) }, type = UUIDArgument(base, name) ) }
addArgument { ListArgument(base, UUIDArgument(base, name), list, parse = { UUID.fromString(it.toString()) }) }

inline fun <reified T : Enum<T>> addEnumArgument(name: String): EnumArgument<T> =
addArgument { EnumArgument<T>(base, name, T::class) }
addArgument { EnumArgument<T>(base, StringArgument(base, name, StringType.WORD), T::class) }

inline fun <reified T : Enum<T>> addEnumArgument(
name: String,
noinline stringifier: (Enum<*>) -> String = { it.name },
noinline parse: (String) -> Enum<T>?
): EnumArgument<T> = addArgument { EnumArgument(base, name, T::class, stringifier, parse) }
noinline converter: (Enum<*>?) -> Suggestion = { Suggestion.withText(it?.name ?: "") },
noinline parse: (Any?) -> Enum<T>?
): EnumArgument<T> = addArgument { EnumArgument(base, StringArgument(base, name, StringType.WORD), T::class, converter, parse) }

fun addEntityArgument(name: String, type: EntityDisplayType): EntityArgument =
addArgument { EntityArgument(base, name, type) }
Expand Down Expand Up @@ -209,24 +213,21 @@ open class ArgumentHandler {
addArgument {
ListArgument(
base,
name,
Bukkit.getOnlinePlayers().toList(),
{ it.name },
{ Bukkit.getPlayer(it) },
StringArgument(base, name, StringType.WORD)
StringArgument(base, name, StringType.WORD),
{ Bukkit.getOnlinePlayers().toList() },
{ Suggestion.withText(it.name) },
{ Bukkit.getPlayer(it.toString()) },
)
}

@Suppress("DEPRECATION")
fun addOfflinePlayersArgument(name: String): ListArgument<OfflinePlayer> =
addArgument {
ListArgument(
base,
name,
Bukkit.getOfflinePlayers().toList(),
{ it.name!! },
{ Bukkit.getOfflinePlayer(it) },
StringArgument(base, name, StringType.WORD)
StringArgument(base, name, StringType.WORD),
{ Bukkit.getOfflinePlayers().toList() },
{ Suggestion.withText(it.name!!) },
{ Bukkit.getOfflinePlayer(it.toString()) },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ package com.undefined.stellar.argument.types.custom

import com.undefined.stellar.AbstractStellarCommand
import com.undefined.stellar.argument.AbstractStellarArgument
import com.undefined.stellar.data.suggestion.Suggestion
import java.lang.Enum.valueOf
import kotlin.reflect.KClass

@Suppress("UNCHECKED_CAST")
class EnumArgument<T : Enum<T>>(
parent: AbstractStellarCommand<*>,
name: String,
type: AbstractStellarArgument<*>,
val enum: KClass<out Enum<*>>,
val stringifier: (Enum<*>) -> String = { it.name },
val parse: (String) -> Enum<T>? = {
converter: (Enum<*>?) -> Suggestion = { Suggestion.withText(it?.name ?: "") },
parse: (Any?) -> Enum<T>? = {
try {
valueOf(enum.java, name) as Enum<T>
valueOf(enum.java, type.name) as Enum<T>
} catch (e: IllegalArgumentException) {
null
}
}
) : AbstractStellarArgument<EnumArgument<T>>(parent, name) {
) : ListArgument<Enum<*>?>(parent, type, enum.java.enumConstants.toList(), converter, parse) {

fun getStringList(): List<String> = enum.java.enumConstants.map(stringifier)
fun valueOf(name: String): Enum<T>? =
try {
valueOf(enum.java, name) as Enum<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ package com.undefined.stellar.argument.types.custom

import com.undefined.stellar.AbstractStellarCommand
import com.undefined.stellar.argument.AbstractStellarArgument
import com.undefined.stellar.data.suggestion.StellarSuggestion
import com.undefined.stellar.data.suggestion.Suggestion
import org.bukkit.command.CommandSender

open class ListArgument<T>(
parent: AbstractStellarCommand<*>,
name: String,
val type: AbstractStellarArgument<*>,
val list: () -> List<T>,
val stringifier: (T) -> String = { it.toString() },
val parse: (String) -> T?,
val type: AbstractStellarArgument<*>
) : AbstractStellarArgument<ListArgument<T>>(parent, name) {
val converter: (T) -> Suggestion = { Suggestion.withText(it.toString()) },
val parse: (Any?) -> T?
) : AbstractStellarArgument<ListArgument<T>>(parent, type.name) {

constructor(parent: AbstractStellarCommand<*>,
name: String,
type: AbstractStellarArgument<*>,
list: List<T>,
stringifier: (T) -> String = { it.toString() },
parse: (String) -> T?,
type: AbstractStellarArgument<*>) : this(parent, name, { list }, stringifier, parse, type)
converter: (T) -> Suggestion = { Suggestion.withText(it.toString()) },
parse: (Any?) -> T?) : this(parent, type, { list }, converter, parse)

fun getStringList(): List<String> = list().map(stringifier)
override val suggestions: MutableList<StellarSuggestion<*>>
get() = (super.suggestions + StellarSuggestion(CommandSender::class) { getSuggestionList() }).toMutableList()

fun getSuggestionList(): List<Suggestion> = list().map(converter)

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ class CommandContext<T : CommandSender>(val arguments: CommandNode, val sender:
val argument = arguments[name] ?: throw NoSuchElementException("No argument with the name $name")
val context = this as CommandContext<CommandSender>
return argument(context) as? T
?: throw ArgumentCastMismatchException("Argument of index $name cannot be cast into ${T::class.simpleName}!")
?: throw ArgumentCastMismatchException("Argument of name '$name' cannot be cast into ${T::class.simpleName}! Check if the argument you are getting returns this class.")
}

inline fun <reified T> getArgument(index: Int): T =
arguments.values.toList()[index](this as CommandContext<CommandSender>) as? T
?: throw ArgumentCastMismatchException("Argument of index $index cannot be cast into ${T::class.simpleName}!")
?: throw ArgumentCastMismatchException("Argument of index '$index' cannot be cast into ${T::class.simpleName}! Check if the argument you are getting returns this class.")

operator fun get(index: Int) = arguments.values.toList()[index](this as CommandContext<CommandSender>)
operator fun get(name: String) = (arguments[name]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import org.bukkit.command.CommandSender
import kotlin.reflect.KClass
import kotlin.reflect.safeCast

data class StellarSuggestion<C : CommandSender>(val clazz: KClass<C>, val suggestion: CommandContext<C>.() -> List<Suggestion>) {
fun get(context: CommandContext<C>): List<Suggestion> {
@Suppress("UNCHECKED_CAST")
data class StellarSuggestion<C : CommandSender>(private val clazz: KClass<C>, private val suggestion: CommandContext<C>.() -> List<Suggestion>) {
fun get(context: CommandContext<CommandSender>): List<Suggestion> {
if (clazz.safeCast(context.sender) == null) return listOf()
return suggestion(context)
return suggestion(context as CommandContext<C>)
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
package com.undefined.stellar.data.suggestion

data class Suggestion(val title: String, val tooltip: String)
data class Suggestion(val text: String, val tooltip: String) {

companion object {
fun withText(text: String): Suggestion = Suggestion(text, "")
}

}
6 changes: 3 additions & 3 deletions server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ val groupIdVar = "com.undefined"
val artifactIdVar = "stellar"

dependencies {
compileOnly("org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT")
compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT")

implementation(project(":api"))
implementation(project(":common"))
Expand All @@ -21,7 +21,7 @@ dependencies {
implementation(project(":v1_21_1:", "reobf"))
implementation(project(":v1_21_3:", "reobf"))
implementation(project(":v1_21_4:", "reobf"))
compileOnly(project(":v1_20_1"))
compileOnly(project(":v1_20_6"))
}

tasks {
Expand All @@ -38,7 +38,7 @@ tasks {
}

runServer {
minecraftVersion("1.20.1")
minecraftVersion("1.20.6")
jvmArgs("-Xmx2G")
}
}
Expand Down
14 changes: 6 additions & 8 deletions server/src/main/kotlin/com/undefined/stellar/Main.kt
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
package com.undefined.stellar

import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.scoreboard.DisplaySlot

class Main : JavaPlugin() {

override fun onEnable() {
StellarCommand("test")
.addLocationArgument("location")
.addDisplaySlotArgument("string")
val main = StellarCommand("test")
main.addLocationArgument("location")
.addRequirements(4)
.addOnlinePlayersArgument("string")
.addExecution<Player> {
sender.sendMessage(this.getArgument<DisplaySlot>("string").name)
}
.addRequirement<Player> {
this.hasPlayedBefore()
sender.sendMessage(this.getArgument<Player>("string").name)
}
.register(this)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ object ArgumentHelper {
fun <T : AbstractStellarArgument<*>> getArgumentType(argument: T): ArgumentType<*> =
when (argument) {
is ListArgument<*> -> getArgumentType(argument.type)
is EnumArgument<*> -> StringArgumentType.word()
is CustomArgument<*> -> getArgumentType(argument.type)
is StringArgument -> brigadier(argument.type)
is GreedyStringArgument -> brigadier(StringType.PHRASE)
Expand All @@ -129,13 +128,9 @@ object ArgumentHelper {
LocationType.DOUBLE_LOCATION_2D -> Vec2Argument.vec2()
}
is BlockDataArgument -> BlockStateArgument.block(COMMAND_BUILD_CONTEXT)
is com.undefined.stellar.argument.types.block.BlockPredicateArgument -> BlockPredicateArgument.blockPredicate(
COMMAND_BUILD_CONTEXT
)
is com.undefined.stellar.argument.types.block.BlockPredicateArgument -> BlockPredicateArgument.blockPredicate(COMMAND_BUILD_CONTEXT)
is com.undefined.stellar.argument.types.item.ItemArgument -> ItemArgument.item(COMMAND_BUILD_CONTEXT)
is com.undefined.stellar.argument.types.item.ItemPredicateArgument -> ItemPredicateArgument.itemPredicate(
COMMAND_BUILD_CONTEXT
)
is com.undefined.stellar.argument.types.item.ItemPredicateArgument -> ItemPredicateArgument.itemPredicate(COMMAND_BUILD_CONTEXT)
is com.undefined.stellar.argument.types.text.ColorArgument -> ColorArgument.color()
is com.undefined.stellar.argument.types.text.ComponentArgument -> ComponentArgument.textComponent()
is com.undefined.stellar.argument.types.text.StyleArgument -> throwArgumentVersionException(argument)
Expand Down Expand Up @@ -204,8 +199,7 @@ object ArgumentHelper {
is FloatArgument -> FloatArgumentType.getFloat(context, argument.name)
is DoubleArgument -> DoubleArgumentType.getDouble(context, argument.name)
is BooleanArgument -> BoolArgumentType.getBool(context, argument.name)
is ListArgument<*> -> argument.parse(StringArgumentType.getString(context, argument.name))
is EnumArgument<*> -> argument.parse(StringArgumentType.getString(context, argument.name))
is ListArgument<*> -> argument.parse(getParsedArgument(context, argument))
is com.undefined.stellar.argument.types.entity.EntityArgument -> EntityArgument.getEntities(context, argument.name)
.map { it.bukkitEntity }.toMutableList()
.addAll(listOf(EntityArgument.getEntity(context, argument.name).bukkitEntity))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ object BrigadierCommandHelper {
}

fun fulfillsRequirements(command: AbstractStellarCommand<*>, source: CommandSourceStack): Boolean {
println(source.bukkitSender::class.simpleName)
val fulfillsExecutionRequirements = command.requirements.all { it(source.bukkitSender) }
val fulfillsPermissionRequirements = command.permissionRequirements.all { source.hasPermission(it.level, it.permission) }
return fulfillsExecutionRequirements.and(fulfillsPermissionRequirements)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ object BrigadierCommandHelper {
}

fun fulfillsRequirements(command: AbstractStellarCommand<*>, source: CommandSourceStack): Boolean {
println(source.bukkitSender::class.simpleName)
val fulfillsExecutionRequirements = command.requirements.all { it(source.bukkitSender) }
val fulfillsPermissionRequirements = command.permissionRequirements.all { source.hasPermission(it.level, it.permission) }
return fulfillsExecutionRequirements.and(fulfillsPermissionRequirements)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ object BrigadierCommandHelper {
}

fun fulfillsRequirements(command: AbstractStellarCommand<*>, source: CommandSourceStack): Boolean {
println(source.bukkitSender::class.simpleName)
val fulfillsExecutionRequirements = command.requirements.all { it(source.bukkitSender) }
val fulfillsPermissionRequirements = command.permissionRequirements.all { source.hasPermission(it.level, it.permission) }
return fulfillsExecutionRequirements.and(fulfillsPermissionRequirements)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ object ArgumentHelper {
fun <T : AbstractStellarArgument<*>> getArgumentType(argument: T): ArgumentType<*> =
when (argument) {
is ListArgument<*> -> getArgumentType(argument.type)
is EnumArgument<*> -> StringArgumentType.word()
is CustomArgument<*> -> getArgumentType(argument.type)
is StringArgument -> brigadier(argument.type)
is GreedyStringArgument -> brigadier(StringType.PHRASE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package com.undefined.stellar.v1_20_6

import com.mojang.brigadier.builder.LiteralArgumentBuilder
import com.mojang.brigadier.context.CommandContext
import com.mojang.brigadier.suggestion.Suggestions
import com.mojang.brigadier.suggestion.SuggestionsBuilder
import com.mojang.brigadier.tree.LiteralCommandNode
import com.undefined.stellar.AbstractStellarCommand
import com.undefined.stellar.argument.AbstractStellarArgument
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import net.minecraft.commands.CommandSourceStack
import net.minecraft.server.MinecraftServer
import java.util.concurrent.CompletableFuture

object BrigadierCommandHelper {

Expand All @@ -34,6 +37,18 @@ object BrigadierCommandHelper {
return fulfillsExecutionRequirements.and(fulfillsPermissionRequirements)
}

fun handleSuggestions(
command: AbstractStellarArgument<*>,
context: CommandContext<CommandSourceStack>,
builder: SuggestionsBuilder
): CompletableFuture<Suggestions>? {
val stellarContext = CommandContextAdapter.getStellarCommandContext(context)
for (stellarSuggestion in command.suggestions)
for (suggestion in stellarSuggestion.get(stellarContext))
builder.suggest(suggestion.text) { suggestion.tooltip }
return builder.buildFuture()
}

fun handleFailureMessageAndExecutions(command: AbstractStellarCommand<*>, context: CommandContext<CommandSourceStack>) {
for (execution in command.failureExecutions) execution(CommandContextAdapter.getStellarCommandContext(context))
for (message in command.failureMessages) context.source.bukkitSender.sendMessage(LegacyComponentSerializer.legacySection().serialize(message))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package com.undefined.stellar.v1_20_6
import com.mojang.brigadier.Command
import com.mojang.brigadier.builder.ArgumentBuilder
import com.mojang.brigadier.builder.LiteralArgumentBuilder
import com.mojang.brigadier.builder.RequiredArgumentBuilder
import com.undefined.stellar.AbstractStellarCommand
import com.undefined.stellar.argument.AbstractStellarArgument
import com.undefined.stellar.argument.LiteralStellarArgument
import com.undefined.stellar.argument.types.custom.ListArgument
import com.undefined.stellar.argument.types.primitive.GreedyStringArgument
import net.minecraft.commands.CommandSourceStack

Expand All @@ -26,6 +28,13 @@ object CommandAdapter {
brigadierCommand.requires { source ->
BrigadierCommandHelper.fulfillsRequirements(command, source)
}

println("1!\n")
if (command !is AbstractStellarArgument || command.suggestions.isEmpty() || brigadierCommand !is RequiredArgumentBuilder<CommandSourceStack, *>) return
println("suggestions!\n")
brigadierCommand.suggests { context, builder ->
BrigadierCommandHelper.handleSuggestions(command, context, builder)
}
}

fun handleArguments(command: AbstractStellarCommand<*>, brigadierCommand: ArgumentBuilder<CommandSourceStack, *>) {
Expand Down

0 comments on commit 91ad273

Please sign in to comment.