Skip to content

Commit

Permalink
refactor(commands): Pass arguments through executes block
Browse files Browse the repository at this point in the history
feat(commands): Support trailing default arguments
  • Loading branch information
0ffz committed Oct 24, 2024
1 parent 06368ad commit 58ba9be
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
package com.mineinabyss.idofront

import com.mineinabyss.idofront.commands.brigadier.Args
import com.mineinabyss.idofront.commands.brigadier.ArgsMinecraft
import com.mineinabyss.idofront.commands.brigadier.commands
import com.mineinabyss.idofront.commands.brigadier.executes
import com.mineinabyss.idofront.di.DI
import com.mineinabyss.idofront.plugin.listeners
import com.mineinabyss.idofront.serialization.recipes.options.IngredientOptionsListener
import kotlinx.coroutines.flow.merge
import org.bukkit.entity.Player
import org.bukkit.plugin.java.JavaPlugin

class IdofrontPlugin : JavaPlugin() {
override fun onEnable() {
val recipeOptionsListener = IngredientOptionsListener(this)
DI.add(recipeOptionsListener)
listeners(recipeOptionsListener)

commands {
"idofront" {
"msg" {
executes(
Args.string(),
ArgsMinecraft.player().resolve()
.map { it.single() }
.default { sender as? Player ?: fail("Receiver should be player") },
Args.integer(min = 0).default { 1 }
) { msg, player, times ->
repeat(times) {
player.sendMessage(msg)
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.mineinabyss.idofront.commands.brigadier

import com.mojang.brigadier.arguments.ArgumentType


inline fun <reified A: Any> IdoCommand.executes(
a: ArgumentType<A>,
crossinline run: IdoCommandContext.(A) -> Unit
) {
executesDefaulting(a) { (a) -> run(arg<A>(a)) }
}

inline fun <reified A: Any, reified B: Any> IdoCommand.executes(
a: ArgumentType<A>,
b: ArgumentType<B>,
crossinline run: IdoCommandContext.(A, B) -> Unit
) {
executesDefaulting(a, b) { (a, b) -> run(arg<A>(a), arg<B>(b)) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any> IdoCommand.executes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
crossinline run: IdoCommandContext.(A, B, C) -> Unit
) {
executesDefaulting(a, b, c) { (a, b, c) -> run(arg<A>(a), arg<B>(b), arg<C>(c)) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any, reified D: Any> IdoCommand.executes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
d: ArgumentType<D>,
crossinline run: IdoCommandContext.(A, B, C, D) -> Unit
) {
executesDefaulting(a, b, c, d) { (a, b, c, d) -> run(arg<A>(a), arg<B>(b), arg<C>(c), arg<D>(d)) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any, reified D: Any, reified E: Any> IdoCommand.executes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
d: ArgumentType<D>,
e: ArgumentType<E>,
crossinline run: IdoCommandContext.(A, B, C, D, E) -> Unit
) {
executesDefaulting(a, b, c, d, e) { (a, b, c, d, e) -> run(arg<A>(a), arg<B>(b), arg<C>(c), arg<D>(d), arg<E>(e)) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any, reified D: Any, reified E: Any, reified F: Any> IdoCommand.executes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
d: ArgumentType<D>,
e: ArgumentType<E>,
f: ArgumentType<F>,
crossinline run: IdoCommandContext.(A, B, C, D, E, F) -> Unit
) {
executesDefaulting(a, b, c, d, e, f) { run(arg<A>(it[0]), arg<B>(it[1]), arg<C>(it[2]), arg<D>(it[3]), arg<E>(it[4]), arg<F>(it[5])) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.mineinabyss.idofront.commands.brigadier

import com.mojang.brigadier.arguments.ArgumentType


inline fun <reified A: Any> IdoCommand.playerExecutes(
a: ArgumentType<A>,
crossinline run: IdoCommandContext.(A) -> Unit
) {
val rA = registerArgument(a, "a")
playerExecutes { run(rA()) }
}

inline fun <reified A: Any, reified B: Any> IdoCommand.playerExecutes(
a: ArgumentType<A>,
b: ArgumentType<B>,
crossinline run: IdoCommandContext.(A, B) -> Unit
) {
val rA = registerArgument(a, "a")
val rB = registerArgument(b, "b")
playerExecutes { run(rA(), rB()) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any> IdoCommand.playerExecutes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
crossinline run: IdoCommandContext.(A, B, C) -> Unit
) {
val rA = registerArgument(a, "a")
val rB = registerArgument(b, "b")
val rC = registerArgument(c, "c")
playerExecutes { run(rA(), rB(), rC()) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any, reified D: Any> IdoCommand.playerExecutes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
d: ArgumentType<D>,
crossinline run: IdoCommandContext.(A, B, C, D) -> Unit
) {
val rA = registerArgument(a, "a")
val rB = registerArgument(b, "b")
val rC = registerArgument(c, "c")
val rD = registerArgument(d, "d")
playerExecutes { run(rA(), rB(), rC(), rD()) }
}

inline fun <reified A: Any, reified B: Any, reified C: Any, reified D: Any, reified E: Any> IdoCommand.playerExecutes(
a: ArgumentType<A>,
b: ArgumentType<B>,
c: ArgumentType<C>,
d: ArgumentType<D>,
e: ArgumentType<E>,
crossinline run: IdoCommandContext.(A, B, C, D, E) -> Unit
) {
val rA = registerArgument(a, "a")
val rB = registerArgument(b, "b")
val rC = registerArgument(c, "c")
val rD = registerArgument(d, "d")
val rE = registerArgument(e, "e")
playerExecutes { run(rA(), rB(), rC(), rD(), rE()) }
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.mineinabyss.idofront.commands.brigadier

import io.papermc.paper.command.brigadier.CommandSourceStack
import kotlin.reflect.KProperty

class IdoArgument<T>(
val name: String,
val resolve: ((CommandSourceStack, Any) -> T)? = null,
val default: ((IdoCommandContext) -> T)? = null,
) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): IdoArgument<T> {
return this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,86 @@
package com.mineinabyss.idofront.commands.brigadier

import com.github.shynixn.mccoroutine.bukkit.asyncDispatcher
import com.github.shynixn.mccoroutine.bukkit.scope
import com.mojang.brigadier.StringReader
import com.mojang.brigadier.arguments.ArgumentType
import com.mojang.brigadier.context.CommandContext
import com.mojang.brigadier.suggestion.SuggestionProvider
import com.mojang.brigadier.suggestion.Suggestions
import com.mojang.brigadier.suggestion.SuggestionsBuilder
import io.papermc.paper.command.brigadier.CommandSourceStack
import io.papermc.paper.command.brigadier.argument.CustomArgumentType
import kotlinx.coroutines.future.future
import org.bukkit.Bukkit
import java.util.concurrent.CompletableFuture
import kotlin.reflect.KClass

data class IdoArgumentBuilder<T>(
val type: ArgumentType<out T>,
val suggestions: (suspend IdoSuggestionsContext.() -> Unit)? = null,
)
data class IdoArgumentParser<T : Any, R>(
val parse: (StringReader) -> T,
val resolve: (CommandSourceStack, T) -> R,
) {
fun <New> map(map: (CommandSourceStack, R) -> New): IdoArgumentParser<T, New> =
IdoArgumentParser(parse, resolve = { stack, value -> map(stack, resolve(stack, value)) })
}

data class IdoArgumentType<T>(
val nativeType: ArgumentType<Any>,
// val nativeKClass: KClass<*>,
val parser: IdoArgumentParser<*, T>,
val suggestions: (CommandContext<Any>, SuggestionsBuilder) -> CompletableFuture<Suggestions>,
val commandExamples: MutableCollection<String>,
val default: ((IdoCommandContext) -> T)? = null,
) : ArgumentType<T> {
fun createType() = object : CustomArgumentType<Any, Any> {
override fun parse(reader: StringReader): Any = parser.parse(reader)

override fun <S : Any?> listSuggestions(
context: CommandContext<S>,
builder: SuggestionsBuilder,
) = suggestions(context as CommandContext<Any>, builder)

override fun getExamples() = this@IdoArgumentType.commandExamples
override fun getNativeType(): ArgumentType<Any> = this@IdoArgumentType.nativeType
}

override fun parse(reader: StringReader?) =
error("IdoArgumentType should not be parsed directly, call createType() instead.")

inline fun suggests(crossinline suggestions: suspend IdoSuggestionsContext.() -> Unit): IdoArgumentType<T> =
copy(
suggestions = { context, builder ->
val plugin = Bukkit.getPluginManager().getPlugin("Idofront")!!
plugin.scope.future(plugin.asyncDispatcher) {
suggestions(IdoSuggestionsContext(context as CommandContext<CommandSourceStack>, builder))
builder.build()
}
}
)

fun suggests(provider: SuggestionProvider<CommandSourceStack>): IdoArgumentType<T> = copy(
suggestions = { context, suggestions ->
provider.getSuggestions(
context as CommandContext<CommandSourceStack>,
suggestions
)
},
)

fun default(default: IdoCommandContext.() -> T): IdoArgumentType<T> =
copy(default = default)

inline fun <R> map(crossinline transform: IdoCommandParsingContext.(T) -> R): IdoArgumentType<R> =
IdoArgumentType(
nativeType = nativeType,
// nativeKClass = nativeKClass,
parser = parser.map { stack, value ->
val context = object : IdoCommandParsingContext {
override val stack = stack
}
transform(context, value)
},
suggestions = suggestions,
commandExamples = commandExamples
)

}
Loading

0 comments on commit 58ba9be

Please sign in to comment.