Skip to content
This repository has been archived by the owner on Jan 28, 2020. It is now read-only.

Add CommandOptions, add a few more CommandTypeAdapters and update ExampleCommand #10

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,4 @@
<scope>provided</scope>
</dependency>
</dependencies>


</project>
15 changes: 12 additions & 3 deletions src/main/kotlin/com/qrakn/honcho/Honcho.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.qrakn.honcho

import com.qrakn.honcho.command.CommandOption
import com.qrakn.honcho.command.adapter.CommandTypeAdapter
import com.qrakn.honcho.command.adapter.impl.PlayerTypeAdapter
import com.qrakn.honcho.command.adapter.impl.StringTypeAdapter
import com.qrakn.honcho.command.adapter.impl.*
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.OfflinePlayer
import org.bukkit.entity.Player
import org.bukkit.plugin.java.JavaPlugin

Expand All @@ -13,8 +15,15 @@ class Honcho(val plugin: JavaPlugin) {
var noPermissionMessage = "${ChatColor.RED}You don't have permission to do this."

init {
registerTypeAdapter(String::class.java, StringTypeAdapter())
registerTypeAdapter(Boolean::class.java, BooleanTypeAdapter())
registerTypeAdapter(ChatColor::class.java, ChatColorTypeAdapter())
registerTypeAdapter(Double::class.java, DoubleTypeAdapter())
registerTypeAdapter(GameMode::class.java, GameModeTypeAdapter())
registerTypeAdapter(Integer::class.java, IntegerTypeAdapter())
registerTypeAdapter(OfflinePlayer::class.java, OfflinePlayerTypeAdapter())
registerTypeAdapter(CommandOption::class.java, CommandOptionTypeAdapter())
registerTypeAdapter(Player::class.java, PlayerTypeAdapter())
registerTypeAdapter(String::class.java, StringTypeAdapter())
}

fun registerCommand(command: Any) {
Expand Down
67 changes: 53 additions & 14 deletions src/main/kotlin/com/qrakn/honcho/HonchoExecutor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.qrakn.honcho

import com.qrakn.honcho.command.CPL
import com.qrakn.honcho.command.CommandMeta
import com.qrakn.honcho.command.CommandOption
import com.qrakn.honcho.command.adapter.CommandTypeAdapter
import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.apache.commons.lang.StringUtils
Expand All @@ -18,7 +19,7 @@ import org.bukkit.scheduler.BukkitRunnable
import java.lang.Exception
import java.lang.NullPointerException
import java.lang.reflect.Method
import java.util.HashMap
import java.util.*

internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {

Expand All @@ -36,7 +37,7 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
}
}

val binding = CommandBinding(methods.toTypedArray(), command)
val binding = CommandBinding(methods.toTypedArray(), meta, command)
for (label in HonchoCommand.getHierarchicalLabel(command.javaClass, ArrayList())) {
commands[label] = binding

Expand All @@ -57,10 +58,11 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
}
}

fun execute(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
fun execute(sender: CommandSender, command: Command, label: String, args: Array<String?>): Boolean {
val binding: CommandBinding = commands[label] ?: return false
val meta = binding.command.javaClass.getAnnotation(CommandMeta::class.java)
val instance = binding.command
var option = false

if (meta.permission.isNotEmpty() && !sender.hasPermission(meta.permission)) {
var message = honcho.noPermissionMessage
Expand All @@ -78,12 +80,22 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
override fun run() {
outer@ for (method in binding.methods) {
val parameters = method.parameters
var doContinue = true

if (parameters[0].type is Player && sender !is Player) continue
if (method.declaringClass != instance.javaClass) continue

if (method.parameterCount - 1 > args.size) {
continue
for(param in parameters) {
if(param.type == CommandOption::class.java && method.parameterCount - 2 <= args.size) {
doContinue = false
break
}
}

if(doContinue) {
continue
}
}

/**
Expand Down Expand Up @@ -119,15 +131,23 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
}

try {
val conversion = adapter.convert(input, parameter.type)
val conversion = adapter.convert(input!!, parameter.type)

if (conversion == null && adapter is NonNullableCommandTypeAdapter) {
throw NullPointerException()
}

if(conversion is CommandOption) {
if(!meta.options.contains(conversion.tag.toLowerCase())) {
sender.sendMessage("${ChatColor.RED}Unrecognized command option '-${conversion.tag}'!")
sender.sendMessage("${ChatColor.RED}Usage: ${command.usage}")
return
}
}

arguments.add(conversion)
} catch (exception: Exception) {
if (!adapter.onException(exception, sender, input)) { // if exception not handled by adapter
if (!adapter.onException(exception, sender, input!!)) { // if exception not handled by adapter
sender.sendMessage("${ChatColor.RED}An error occurred (${exception.message}), please contact an administrator")
}
return
Expand All @@ -154,7 +174,7 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
return true
}

override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<String?>): Boolean {
return execute(sender, command, label, args)
}

Expand All @@ -176,7 +196,19 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
private fun getCommandUsage(label: String): String {
val command = commands[label]!!
val builder = StringBuilder("/").append(label)
val arguments: MutableMap<Int, CommandArguments> = HashMap()
val arguments: MutableMap<Int, CommandArguments?> = HashMap()

if(command.meta.options.isNotEmpty()) {
val options = ArrayList<String>()

command.meta.options.forEach {
options.add("-" + it.toLowerCase())
}

builder.append(" [")
builder.append(StringUtils.join(options, ","))
builder.append("]")
}

for (method in command.methods) {
val parameters = method.parameters
Expand All @@ -191,24 +223,31 @@ internal class HonchoExecutor(private val honcho: Honcho) : CommandExecutor {
parameter.name
}

if (!(argument.arguments.contains(name))) {
argument.arguments.add(name)
arguments[i - 1] = argument
if(parameter.type == CommandOption::class.java) {
arguments[i - 1] = null
} else {
if (argument != null) {
if (!(argument.arguments.contains(name))) {
argument.arguments.add(name)
arguments[i - 1] = argument
}
}
}
}

}

for (index in 0 until arguments.size) {
val argument = arguments[index]

builder.append(" <").append(StringUtils.join(argument?.arguments, "/")).append(">")
if(argument != null) {
builder.append(" <").append(StringUtils.join(argument.arguments, "/")).append(">")
}
}

return builder.toString()
}

private inner class CommandArguments(val arguments: MutableList<String>)
internal inner class CommandBinding(val methods: Array<Method>, val command: Any)
internal inner class CommandBinding(val methods: Array<Method>, val meta: CommandMeta, val command: Any)

}
1 change: 1 addition & 0 deletions src/main/kotlin/com/qrakn/honcho/command/CommandMeta.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package com.qrakn.honcho.command
@Retention(AnnotationRetention.RUNTIME)
annotation class CommandMeta(
vararg val label: String,
val options: Array<String> = [""],
val permission: String = "",
val description: String = "",
val subcommands: Boolean = false,
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/com/qrakn/honcho/command/CommandOption.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.qrakn.honcho.command

class CommandOption(val tag: String)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import org.bukkit.command.CommandSender
import java.lang.Exception

interface CommandTypeAdapter {
fun <T> convert(string: String, type: Class<T>): T
fun <T> convert(string: String, type: Class<T>): T?
fun onException(exception: Exception, sender: CommandSender, input: String): Boolean { return false }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.lang.Exception

class BooleanTypeAdapter : NonNullableCommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T {
return type.cast(MAP[string.toLowerCase()])
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
sender.sendMessage("${ChatColor.RED}The value '$input' is not a boolean. ${ChatColor.GRAY}[yes, no]")
return true
}

companion object {
private val MAP = HashMap<String, Boolean>()

init {
MAP["true"] = true
MAP["on"] = true
MAP["yes"] = true

MAP["false"] = false
MAP["off"] = false
MAP["no"] = false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.lang.Exception

class ChatColorTypeAdapter : NonNullableCommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T? {
return type.cast(ChatColor.valueOf(string.toUpperCase()))
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
sender.sendMessage("${ChatColor.RED}The value '$input' is not a chatcolor. ${ChatColor.GRAY}[RED, DARK_RED]")
return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.CommandOption
import com.qrakn.honcho.command.adapter.CommandTypeAdapter
import org.bukkit.command.CommandSender

class CommandOptionTypeAdapter : CommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T? {
return if (string.startsWith("-")) {
type.cast(CommandOption(string.toLowerCase().substring(1)))
} else null
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
return false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.lang.Exception

class DoubleTypeAdapter : NonNullableCommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T {
return type.cast(string.toDoubleOrNull())
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
sender.sendMessage("${ChatColor.RED}The value '$input' is not a double. ${ChatColor.GRAY}[2.0, 1.2, 1.5]")
return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.command.CommandSender
import java.lang.Exception
import java.util.*

class GameModeTypeAdapter : NonNullableCommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T {
return type.cast(MAP[string.toLowerCase()])
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
sender.sendMessage("${ChatColor.RED}The value '$input' is not a gamemode. ${ChatColor.GRAY}[creative, 0, a]")
return true
}

companion object {
private val MAP = HashMap<String, GameMode>()

init {
MAP["c"] = GameMode.CREATIVE
MAP["creative"] = GameMode.CREATIVE
MAP["1"] = GameMode.CREATIVE

MAP["s"] = GameMode.SURVIVAL
MAP["survival"] = GameMode.SURVIVAL
MAP["0"] = GameMode.SURVIVAL

MAP["a"] = GameMode.ADVENTURE
MAP["adventure"] = GameMode.ADVENTURE
MAP["2"] = GameMode.ADVENTURE

MAP["sp"] = GameMode.SPECTATOR
MAP["spectator"] = GameMode.SPECTATOR
MAP["3"] = GameMode.SPECTATOR
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.lang.Exception

class IntegerTypeAdapter : NonNullableCommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T {
return type.cast(Integer.parseInt(string))
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
sender.sendMessage("${ChatColor.RED}The value '$input' is not an integer. ${ChatColor.GRAY}[1, 2, 3]")
return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.qrakn.honcho.command.adapter.impl

import com.qrakn.honcho.command.adapter.NonNullableCommandTypeAdapter
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import java.lang.Exception

class OfflinePlayerTypeAdapter : NonNullableCommandTypeAdapter {
override fun <T> convert(string: String, type: Class<T>): T {
return type.cast(Bukkit.getOfflinePlayer(string))
}

override fun onException(exception: Exception, sender: CommandSender, input: String): Boolean {
sender.sendMessage("${ChatColor.RED}The player '$input' could not be found.")
return true
}
}
Loading