Skip to content

Commit

Permalink
Merge pull request #93 from SpigotBasics/separate-tabcomplete
Browse files Browse the repository at this point in the history
Refactored TabCompleter into own interface; refactored common context methods into own class
  • Loading branch information
mfnalex authored Feb 10, 2024
2 parents e8c67ca + c0d6924 commit a37c1ca
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import java.util.logging.Level
class BasicsCommand internal constructor(
var info: CommandInfo,
private var executor: BasicsCommandExecutor?,
private var tabCompleter: BasicsTabCompleter?,
val coreMessages: CoreMessages,
val messageFactory: MessageFactory,
) :
Expand All @@ -34,11 +35,6 @@ class BasicsCommand internal constructor(
permissionMessage = info.permissionMessage.tagParsed("permission", permString).toLegacyString()
}

// private val customUsageMessage = messageFactory.createMessage(
// "<red>Invalid command usage.</red>",
// "<red>Usage: </red><gold><usage></gold>"
// ).tagParsed("usage", usage).tagParsed("command", name)

override fun execute(
sender: CommandSender,
commandLabel: String,
Expand Down Expand Up @@ -108,8 +104,8 @@ class BasicsCommand internal constructor(
args = args.toMutableList(),
location = location,
)
if (executor == null) return mutableListOf()
val result = executor!!.tabComplete(context)
if (tabCompleter == null) return mutableListOf()
val result = tabCompleter!!.tabComplete(context)
return result ?: super.tabComplete(sender, alias, args, location)
}

Expand All @@ -120,5 +116,6 @@ class BasicsCommand internal constructor(
*/
fun disableExecutor() {
executor = null
tabCompleter = null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class BasicsCommandBuilder(
private var usage: String = ""
private var aliases: List<String> = emptyList()
private var executor: BasicsCommandExecutor? = null
private var tabCompleter: BasicsTabCompleter? = null

fun description(description: String) = apply { this.description = description }

Expand All @@ -29,6 +30,8 @@ class BasicsCommandBuilder(

fun executor(executor: BasicsCommandExecutor) = apply { this.executor = executor }

fun tabCompleter(tabCompleter: BasicsTabCompleter) = apply { this.tabCompleter = tabCompleter }

fun executor(executor: (BasicsCommandContext) -> CommandResult?) =
apply {
this.executor =
Expand All @@ -39,6 +42,16 @@ class BasicsCommandBuilder(
}
}

fun tabCompleter(tabCompleter: (BasicsCommandContext) -> MutableList<String>?) =
apply {
this.tabCompleter =
object : BasicsTabCompleter {
override fun tabComplete(context: BasicsCommandContext): MutableList<String>? {
return tabCompleter(context)
}
}
}

fun register(): BasicsCommand {
val command = build()
module.commandManager.registerCommand(command)
Expand All @@ -56,10 +69,11 @@ class BasicsCommandBuilder(
aliases = aliases,
)
return BasicsCommand(
info,
executor ?: error("Executor must be set"),
module.plugin.messages,
module.plugin.messageFactory,
info = info,
executor = executor ?: error("Executor must be set"),
tabCompleter = tabCompleter ?: executor,
coreMessages = module.plugin.messages,
messageFactory = module.plugin.messageFactory,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.github.spigotbasics.core.command

import com.github.spigotbasics.core.messages.CoreMessages
import com.github.spigotbasics.core.messages.MessageFactory
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.permissions.Permission

abstract class BasicsCommandContextHandler(
val coreMessages: CoreMessages,
val messageFactory: MessageFactory,
) {
@Throws(BasicsCommandException::class)
fun requirePlayer(name: String): Player {
val player = Bukkit.getPlayer(name)
if (player == null) {
throw BasicsCommandException(CommandResult.playerNotFound(name))
}
return player
}

@Throws(BasicsCommandException::class)
fun notFromConsole(sender: CommandSender): Player {
if (sender !is Player) {
throw CommandResult.NOT_FROM_CONSOLE.asException()
}
return sender
}

// TODO: In 99% of cases, we should just use requirePlayer(CommandSender) instead of this method
@Throws(BasicsCommandException::class)
fun requirePlayerOrMustSpecifyPlayerFromConsole(sender: CommandSender): Player {
val player = sender as? Player
if (player == null) {
throw CommandResult.MUST_BE_PLAYER_OR_SPECIFY_PLAYER_FROM_CONSOLE.asException()
}
return player
}

@Throws(BasicsCommandException::class)
fun failIfFlagsLeft(context: BasicsCommandContext) {
if (context.flags.isEmpty()) return
throw CommandResult.unknownFlag(context.flags[0]).asException()
}

@Throws(BasicsCommandException::class)
fun failInvalidArgument(argument: String): CommandResult {
throw CommandResult.invalidArgument(argument).asException()
}

fun requirePermission(
sender: CommandSender,
permission: Permission,
) {
if (!sender.hasPermission(permission)) {
throw CommandResult.noPermission(permission).asException()
}
}

// @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")

fun requireItemInHand(player: Player): ItemStack {
val item = player.inventory.itemInMainHand
if (item.type.isAir) {
throw CommandResult.NO_ITEM_IN_HAND.asException()
}
return item
}

fun requireItemInHandOther(player: Player): ItemStack {
val item = player.inventory.itemInMainHand
if (item.type.isAir) {
throw CommandResult.noItemInHandOthers(player).asException()
}
return item
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,86 +3,16 @@ package com.github.spigotbasics.core.command
import com.github.spigotbasics.core.messages.CoreMessages
import com.github.spigotbasics.core.messages.MessageFactory
import com.github.spigotbasics.core.module.BasicsModule
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.permissions.Permission

abstract class BasicsCommandExecutor(module: BasicsModule) {
protected val coreMessages: CoreMessages = module.plugin.messages
protected val messageFactory: MessageFactory = module.plugin.messageFactory
abstract class BasicsCommandExecutor(
coreMessages: CoreMessages,
messageFactory: MessageFactory,
) : BasicsCommandContextHandler(coreMessages, messageFactory), BasicsTabCompleter {
constructor(module: BasicsModule) : this(module.coreMessages, module.messageFactory)

abstract fun execute(context: BasicsCommandContext): CommandResult?

open fun tabComplete(context: BasicsCommandContext): MutableList<String>? {
override fun tabComplete(context: BasicsCommandContext): MutableList<String>? {
return null
}

// TODO: Move these methods into own CommandParser object

@Throws(BasicsCommandException::class)
fun requirePlayer(name: String): Player {
val player = Bukkit.getPlayer(name)
if (player == null) {
throw BasicsCommandException(CommandResult.playerNotFound(name))
}
return player
}

@Throws(BasicsCommandException::class)
fun notFromConsole(sender: CommandSender): Player {
if (sender !is Player) {
throw CommandResult.NOT_FROM_CONSOLE.asException()
}
return sender
}

// TODO: In 99% of cases, we should just use requirePlayer(CommandSender) instead of this method
@Throws(BasicsCommandException::class)
fun requirePlayerOrMustSpecifyPlayerFromConsole(sender: CommandSender): Player {
val player = sender as? Player
if (player == null) {
throw CommandResult.MUST_BE_PLAYER_OR_SPECIFY_PLAYER_FROM_CONSOLE.asException()
}
return player
}

@Throws(BasicsCommandException::class)
fun failIfFlagsLeft(context: BasicsCommandContext) {
if (context.flags.isEmpty()) return
throw CommandResult.unknownFlag(context.flags[0]).asException()
}

@Throws(BasicsCommandException::class)
fun failInvalidArgument(argument: String): CommandResult {
throw CommandResult.invalidArgument(argument).asException()
}

fun requirePermission(
sender: CommandSender,
permission: Permission,
) {
if (!sender.hasPermission(permission)) {
throw CommandResult.noPermission(permission).asException()
}
}

// @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")

fun requireItemInHand(player: Player): ItemStack {
val item = player.inventory.itemInMainHand
if (item.type.isAir) {
throw CommandResult.NO_ITEM_IN_HAND.asException()
}
return item
}

fun requireItemInHandOther(player: Player): ItemStack {
val item = player.inventory.itemInMainHand
if (item.type.isAir) {
throw CommandResult.noItemInHandOthers(player).asException()
}
return item
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.github.spigotbasics.core.command

interface BasicsTabCompleter {
fun tabComplete(context: BasicsCommandContext): MutableList<String>?
}

0 comments on commit a37c1ca

Please sign in to comment.