package moe.nea.notenoughupdates.commands import com.mojang.brigadier.arguments.ArgumentType import com.mojang.brigadier.builder.ArgumentBuilder import com.mojang.brigadier.builder.LiteralArgumentBuilder import com.mojang.brigadier.builder.RequiredArgumentBuilder import com.mojang.brigadier.context.CommandContext import java.lang.reflect.ParameterizedType import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource import moe.nea.notenoughupdates.util.iterate typealias DefaultSource = FabricClientCommandSource inline val > T.context get() = this operator fun > C.get(arg: TypeSafeArg): T { return arg.get(this) } fun literal( name: String, block: LiteralArgumentBuilder.() -> Unit ): LiteralArgumentBuilder = LiteralArgumentBuilder.literal(name).also(block) data class TypeSafeArg(val name: String, val argument: ArgumentType) { val argClass by lazy { argument.javaClass .iterate>> { it.superclass } .map { it.genericSuperclass } .filterIsInstance() .find { it.rawType == ArgumentType::class.java }!! .let { it.actualTypeArguments[0] as Class<*> } } @JvmName("getWithThis") fun CommandContext.get(): T = get(this) fun get(ctx: CommandContext): T { return ctx.getArgument(name, argClass) as T } } fun argument( name: String, argument: ArgumentType, block: RequiredArgumentBuilder.(TypeSafeArg) -> Unit ): RequiredArgumentBuilder = RequiredArgumentBuilder.argument(name, argument).also { block(it, TypeSafeArg(name, argument)) } fun , AT : Any> T.thenArgument( name: String, argument: ArgumentType, block: RequiredArgumentBuilder.(TypeSafeArg) -> Unit ): T = then(argument(name, argument, block)) fun > T.thenLiteral( name: String, block: LiteralArgumentBuilder.() -> Unit ): T = then(literal(name, block)) fun > T.then(node: ArgumentBuilder, block: T.() -> Unit): T = then(node).also(block) fun > T.thenExecute(block: CommandContext.() -> Unit): T = executes { block(it) 1 }