Added commands and messages modules

This commit is contained in:
redtea committed 2023-08-22 03:27:05 +03:00
1 parent ad17e1e15c
commit 5d615bc63e
45 files changed
+457 -89

No files matched your search

@@ -0,0 +1,9 @@
package tech.carcadex.kotlinbukkitkit.commands
import org.bukkit.command.CommandSender
import tech.carcadex.kotlinbukkitkit.commands.annotations.Command
import tech.carcadex.kotlinbukkitkit.commands.annotations.Permission
import tech.carcadex.kotlinbukkitkit.commands.manager.CommandManager
typealias Sender = CommandSender
@@ -0,0 +1,3 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
annotation class Aliases(val aliases: Array<String>)
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class Command(val name: String)
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class Default()
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class Description(val desc: String)
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class Optional()
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class Permission(val perm: String)
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class SubCommand(val name: String)
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class TabComplete(val complete: Array<String>)
@@ -0,0 +1,4 @@
package tech.carcadex.kotlinbukkitkit.commands.annotations
@Retention(AnnotationRetention.RUNTIME)
annotation class Usage(val usage: String)
@@ -0,0 +1,3 @@
package tech.carcadex.kotlinbukkitkit.commands.exceptions
class UnsupportedTypeException(msg: String) : RuntimeException(msg)
@@ -0,0 +1,99 @@
package tech.carcadex.kotlinbukkitkit.commands.manager
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.OfflinePlayer
import org.bukkit.World
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.plugin.Plugin
import tech.carcadex.kotlinbukkitkit.commands.annotations.Command
import tech.carcadex.kotlinbukkitkit.commands.exceptions.UnsupportedTypeException
import tech.carcadex.kotlinbukkitkit.extensions.offlinePlayerOrNull
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KParameter
import kotlin.reflect.KType
import kotlin.reflect.full.callSuspendBy
import kotlin.reflect.full.findAnnotations
import kotlin.reflect.full.hasAnnotation
import kotlin.reflect.full.isSubtypeOf
import kotlin.reflect.jvm.javaType
class CommandManager(val plugin: Plugin) {
private val types = mutableMapOf<String, (String) -> Any?>()
init {
types[CommandSender::class.qualifiedName!!] = { it }
types[String::class.qualifiedName!!] = { it }
types["java.lang.String"] = { it }
types[Int::class.qualifiedName!!] = { it.toInt() }
types["java.lang.Integer"] = { it.toInt() }
types[UInt::class.qualifiedName!!] = { it.toUInt() }
types[Long::class.qualifiedName!!] = { it.toLong() }
types["java.lang.Long"] = { it.toInt() }
types[ULong::class.qualifiedName!!] = { it.toULong() }
types[Short::class.qualifiedName!!] = { it.toShort() }
types["java.lang.Short"] = { it.toInt() }
types[UShort::class.qualifiedName!!] = { it.toUShort() }
types[Float::class.qualifiedName!!] = { it.toFloat() }
types["java.lang.Float"] = { it.toInt() }
types[Double::class.qualifiedName!!] = { it.toDouble() }
types["java.lang.Double"] = { it.toInt() }
types[Byte::class.qualifiedName!!] = { it.toByte() }
types["java.lang.Byte"] = { it.toInt() }
types[UByte::class.qualifiedName!!] = { it.toUByte() }
types[Boolean::class.qualifiedName!!] = { it.toBoolean() }
types["java.lang.Boolean"] = { it.toInt() }
types[Player::class.qualifiedName!!] = { Bukkit.getPlayer(it) }
types[OfflinePlayer::class.qualifiedName!!] = { offlinePlayerOrNull(it) }
types[World::class.qualifiedName!!] = { Bukkit.getWorld(it) }
types[Material::class.qualifiedName!!] = { Material.matchMaterial(it) }
}
private fun register(commandExecutor: CommandExecutor, aliases: Array<String>,
desc: String = "", usage: String = "") {
CommandRegister.reg(plugin, commandExecutor, aliases, desc, usage);
}
fun register(f: KFunction<Unit>) {
if(f.hasAnnotation<Command>()) {
val cmdName = f.findAnnotations<Command>().first().name
val argsParsers = mutableListOf<(String) -> Any?>({
return@mutableListOf types[CommandSender::class.qualifiedName!!]!!(it)
})
for (argType in f.parameters) {
val clazz = Class.forName(argType.type.javaType.typeName)
if(argType.type.javaType.typeName in this.types) {
argsParsers.add(this.types[argType.type.javaType.typeName]!!)
} else if(!clazz.isEnum) throw UnsupportedTypeException("Type ${argType.type.javaType.typeName} is not supported") else {
argsParsers.add {
for(e in clazz.enumConstants) {
if((e as Enum<*>).name.equals(it, ignoreCase = true)) return@add e;
}
throw NoSuchElementException("No such value in enum")
}
}
}
register(CommandExecutor { sender, command, label, args ->
val finalArgs = mutableListOf<Any?>(sender)
finalArgs.addAll(args.mapIndexed { i, it -> argsParsers[i](it) })
val map = mutableMapOf<KParameter, Any?>()
var i = 0;
for(arg in finalArgs) {
map[f.parameters[i]] = arg
++i
}
f.callBy(map)
return@CommandExecutor true;
}, arrayOf(cmdName))
} else throw IllegalArgumentException("It must be a command!")
}
fun type(clazz: KClass<*>, converter: (String) -> Any) {
types[clazz.qualifiedName!!] = converter
}
}
@@ -0,0 +1,47 @@
package tech.carcadex.kotlinbukkitkit.commands.manager
import org.bukkit.Bukkit
import org.bukkit.command.*
import org.bukkit.plugin.Plugin
import java.util.*
class CommandRegister(
aliases: Array<String>,
desc: String?,
usage: String?,
protected val owner: CommandExecutor,
protected val registeredWith: Any,
val pl: Plugin
) : Command(aliases[0], desc!!, usage!!, Arrays.asList(*aliases)), PluginIdentifiableCommand {
override fun execute(sender: CommandSender, label: String, args: Array<String>): Boolean {
if (!testPermission(sender)) {
return true
}
return if (owner.onCommand(sender, this, label, args)) {
true
} else {
sender.sendMessage(usageMessage)
false
}
}
companion object {
fun reg(plugin: Plugin, executor: CommandExecutor, aliases: Array<String>, desc: String?, usage: String?) {
if(aliases.size < 1) throw IllegalArgumentException("Could not found name")
try {
val reg = CommandRegister(aliases, desc, usage, executor, Any(), plugin)
val field = Bukkit.getServer().javaClass.getDeclaredField("commandMap")
field.isAccessible = true
val map = field[Bukkit.getServer()] as CommandMap
map.register(plugin.description.name, reg)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun getPlugin(): Plugin = pl
}