Fix test issues and command issues
- Fixed test config loading (it loaded it twice, probably would've on a regular server too) - Fixed missing permission plugin when testing - Fixed command node casting errors - Fixed event handler lists not being JVM static
This commit is contained in:
parent
529fef1c5f
commit
4f0e05892a
17 changed files with 105 additions and 55 deletions
|
@ -8,6 +8,7 @@ import buttondevteam.core.component.randomtp.RandomTPComponent
|
|||
import buttondevteam.core.component.restart.RestartComponent
|
||||
import buttondevteam.core.component.spawn.SpawnComponent
|
||||
import buttondevteam.core.component.towny.TownyComponent
|
||||
import buttondevteam.lib.ChromaUtils
|
||||
import buttondevteam.lib.TBMCCoreAPI
|
||||
import buttondevteam.lib.architecture.ButtonPlugin
|
||||
import buttondevteam.lib.architecture.Component.Companion.registerComponent
|
||||
|
@ -17,6 +18,7 @@ import buttondevteam.lib.chat.TBMCChatAPI
|
|||
import buttondevteam.lib.player.ChromaGamerBase
|
||||
import buttondevteam.lib.player.TBMCPlayer
|
||||
import buttondevteam.lib.player.TBMCPlayerBase
|
||||
import buttondevteam.lib.test.TestPermissions
|
||||
import com.earth2me.essentials.Essentials
|
||||
import net.milkbowl.vault.economy.Economy
|
||||
import net.milkbowl.vault.permission.Permission
|
||||
|
@ -66,14 +68,16 @@ class MainPlugin : ButtonPlugin {
|
|||
val externalPlayerPermissionGroup get() = iConfig.getData("externalPlayerPermissionGroup", "default")
|
||||
|
||||
constructor() : super()
|
||||
constructor(loader: JavaPluginLoader, description: PluginDescriptionFile, dataFolder: File, file: File) : super(loader, description, dataFolder, file)
|
||||
constructor(loader: JavaPluginLoader, description: PluginDescriptionFile, dataFolder: File, file: File, @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") test: java.lang.Boolean) : super(loader, description, dataFolder, file) {
|
||||
ChromaUtils.isTest = test.booleanValue()
|
||||
}
|
||||
|
||||
|
||||
public override fun pluginEnable() {
|
||||
instance = this
|
||||
val pdf = description
|
||||
setupPermissions()
|
||||
if (!setupEconomy()) //Though Essentials always provides economy, but we don't require Essentials
|
||||
setupPermissions(ChromaUtils.isTest)
|
||||
if (!setupEconomy() && !ChromaUtils.isTest) //Though Essentials always provides economy, but we don't require Essentials
|
||||
logger.warning("No economy plugin found! Components using economy will not be registered.")
|
||||
ConfigData.saveNow(config) // Run pending save tasks
|
||||
registerComponent(this, RestartComponent())
|
||||
|
@ -159,8 +163,10 @@ class MainPlugin : ButtonPlugin {
|
|||
logger.info("Player data saved.")
|
||||
}
|
||||
|
||||
private fun setupPermissions() {
|
||||
permission = setupProvider(Permission::class.java) ?: throw NullPointerException("No permission plugin found!")
|
||||
private fun setupPermissions(test: Boolean) {
|
||||
permission = setupProvider(Permission::class.java)
|
||||
?: if (test) TestPermissions()
|
||||
else throw NullPointerException("No permission plugin found!")
|
||||
}
|
||||
|
||||
private fun setupEconomy(): Boolean {
|
||||
|
@ -182,6 +188,7 @@ class MainPlugin : ButtonPlugin {
|
|||
|
||||
companion object {
|
||||
lateinit var instance: MainPlugin
|
||||
private set
|
||||
|
||||
lateinit var permission: Permission
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package buttondevteam.core
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit
|
||||
import buttondevteam.core.component.channel.Channel
|
||||
import buttondevteam.core.component.channel.ChannelComponent
|
||||
import buttondevteam.lib.ChromaUtils.isTest
|
||||
import buttondevteam.lib.architecture.Component.Companion.registerComponent
|
||||
import buttondevteam.lib.chat.Color
|
||||
import buttondevteam.lib.chat.TBMCChatAPI.registerChatChannel
|
||||
import org.bukkit.ChatColor
|
||||
|
||||
@Deprecated("Use MockBukkit")
|
||||
object TestPrepare {
|
||||
@JvmStatic
|
||||
fun prepareServer() {
|
||||
isTest = true //Needs to be in a separate class because of the potential lack of Mockito
|
||||
MockBukkit.mock()
|
||||
registerComponent(MockBukkit.load(MainPlugin::class.java), ChannelComponent())
|
||||
registerChatChannel(Channel("${ChatColor.WHITE}g${ChatColor.WHITE}", Color.White, "g", null).also { Channel.globalChat = it })
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ class ScheduledServerRestartEvent(val restartTicks: Int, val command: ScheduledR
|
|||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList = HandlerList()
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ class TBMCChatEvent(
|
|||
val isFromCommand get() = chatMessage.isFromCommand
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList = HandlerList()
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ class TBMCChatPreprocessEvent(val sender: Command2Sender, val channel: Channel,
|
|||
override fun setCancelled(cancelled: Boolean) = run { this.cancelled = cancelled }
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList = HandlerList()
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ class TBMCCommandPreprocessEvent(
|
|||
override fun setCancelled(cancelled: Boolean) = run { this.cancelled = cancelled }
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList = HandlerList()
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ class TBMCExceptionEvent(val sourceMessage: String, val exception: Throwable) :
|
|||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList = HandlerList()
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ class TBMCSystemChatEvent(
|
|||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList = HandlerList()
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import buttondevteam.core.ComponentManager
|
|||
import buttondevteam.lib.TBMCCoreAPI
|
||||
import buttondevteam.lib.chat.Command2MC
|
||||
import buttondevteam.lib.chat.ICommand2MC
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.configuration.InvalidConfigurationException
|
||||
import org.bukkit.configuration.file.FileConfiguration
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
|
@ -50,8 +51,9 @@ abstract class ButtonPlugin : JavaPlugin {
|
|||
*/
|
||||
protected open fun pluginPreDisable() {}
|
||||
override fun onEnable() {
|
||||
if (!tryReloadConfig()) {
|
||||
if (!isConfigLoaded) {
|
||||
logger.warning("Please fix the issues and restart the server to load the plugin.")
|
||||
Bukkit.getPluginManager().disablePlugin(this)
|
||||
return
|
||||
}
|
||||
try {
|
||||
|
@ -65,6 +67,7 @@ abstract class ButtonPlugin : JavaPlugin {
|
|||
|
||||
override fun onDisable() {
|
||||
try {
|
||||
if (!isConfigLoaded) return
|
||||
pluginPreDisable()
|
||||
ComponentManager.unregComponents(this)
|
||||
pluginDisable()
|
||||
|
|
|
@ -80,7 +80,7 @@ class ConfigData<T : Any?> internal constructor(
|
|||
if (config != null) {
|
||||
config.set(path, `val`)
|
||||
signalChange(this.config)
|
||||
} else {
|
||||
} else if (!ChromaUtils.isTest) {
|
||||
ChromaUtils.logWarn("Attempted to get/set config value with no config! Path: $path, value: $`val`")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package buttondevteam.lib.chat
|
|||
import buttondevteam.core.MainPlugin
|
||||
import buttondevteam.lib.TBMCCoreAPI
|
||||
import buttondevteam.lib.chat.commands.*
|
||||
import buttondevteam.lib.chat.commands.CommandUtils.core
|
||||
import buttondevteam.lib.chat.commands.CommandUtils.coreCommand
|
||||
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.arguments.*
|
||||
|
@ -164,14 +164,14 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
*/
|
||||
private fun getExecutableNode(method: Method, command: TC, ann: Subcommand, remainingPath: String,
|
||||
argHelpManager: CommandArgumentHelpManager<TC, TP>, fullPath: String): LiteralCommandNode<TP> {
|
||||
val (params, _) = getCommandParametersAndSender(method, argHelpManager) // Param order is important
|
||||
val (params, senderType) = getCommandParametersAndSender(method, argHelpManager) // Param order is important
|
||||
val paramMap = HashMap<String, CommandArgument>()
|
||||
for (param in params) {
|
||||
paramMap[param.name] = param
|
||||
}
|
||||
val helpText = command.getHelpText(method, ann)
|
||||
val node = CoreCommandBuilder.literal(
|
||||
remainingPath, params[0].type, paramMap, params, command,
|
||||
remainingPath, senderType, paramMap, params, command,
|
||||
{ helpText }, // TODO: Help text getter support
|
||||
{ sender: TP, data: SubcommandData<TC, TP> -> hasPermission(sender, data) },
|
||||
method.annotations.filterNot { it is Subcommand }.toTypedArray(),
|
||||
|
@ -364,9 +364,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
* @return A set of command node objects containing the commands
|
||||
*/
|
||||
val commandNodes: Set<CoreCommandNode<TP, NoOpSubcommandData>>
|
||||
get() = dispatcher.root.children.stream()
|
||||
.map { node: CommandNode<TP> -> node.core<TP, NoOpSubcommandData>() }
|
||||
.collect(Collectors.toUnmodifiableSet())
|
||||
get() = dispatcher.root.children.mapNotNull { it.coreCommand<TP, NoOpSubcommandData>() }.toSet()
|
||||
|
||||
/**
|
||||
* Get a node that belongs to the given command.
|
||||
|
@ -375,7 +373,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
* @return A command node
|
||||
*/
|
||||
fun getCommandNode(command: String): CoreCommandNode<TP, NoOpSubcommandData>? { // TODO: What should this return? No-op? Executable? What's the use case?
|
||||
return dispatcher.root.getChild(command)?.core()
|
||||
return dispatcher.root.getChild(command)?.coreCommand()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -394,7 +392,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
*/
|
||||
fun unregisterCommandIf(condition: Predicate<CoreCommandNode<TP, SubcommandData<TC, TP>>>, nested: Boolean) {
|
||||
dispatcher.root.children.removeIf { node -> node.coreExecutable<TP, TC>()?.let { condition.test(it) } ?: false }
|
||||
if (nested) for (child in dispatcher.root.children) unregisterCommandIf(condition, child.core())
|
||||
if (nested) for (child in dispatcher.root.children) child.coreCommand<_, NoOpSubcommandData>()?.let { unregisterCommandIf(condition, it) }
|
||||
}
|
||||
|
||||
private fun unregisterCommandIf(
|
||||
|
@ -404,7 +402,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
// TODO: Remvoe no-op nodes without children
|
||||
// Can't use getCoreChildren() here because the collection needs to be modifiable
|
||||
root.children.removeIf { node -> node.coreExecutable<TP, TC>()?.let { condition.test(it) } ?: false }
|
||||
for (child in root.children) unregisterCommandIf(condition, child.core())
|
||||
for (child in root.children) child.coreCommand<_, NoOpSubcommandData>()?.let { unregisterCommandIf(condition, it) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,7 +415,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
mainCommand: LiteralCommandNode<TP>,
|
||||
deep: Boolean = true
|
||||
): List<CoreExecutableNode<TP, TC>> {
|
||||
return getSubcommands(deep, mainCommand.core())
|
||||
return mainCommand.coreCommand<_, NoOpSubcommandData>()?.let { getSubcommands(deep, it) } ?: emptyList()
|
||||
}
|
||||
|
||||
private fun getSubcommands(
|
||||
|
@ -425,6 +423,6 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
root: CoreNoOpNode<TP>
|
||||
): List<CoreExecutableNode<TP, TC>> {
|
||||
return root.children.mapNotNull { it.coreExecutable<TP, TC>() } +
|
||||
if (deep) root.children.flatMap { getSubcommands(deep, it.core()) } else emptyList()
|
||||
if (deep) root.children.flatMap { child -> child.coreCommand<_, NoOpSubcommandData>()?.let { getSubcommands(deep, it) } ?: emptyList() } else emptyList()
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package buttondevteam.lib.chat
|
||||
|
||||
import buttondevteam.core.MainPlugin
|
||||
import buttondevteam.lib.ChromaUtils
|
||||
import buttondevteam.lib.TBMCCoreAPI
|
||||
import buttondevteam.lib.architecture.ButtonPlugin
|
||||
import buttondevteam.lib.architecture.Component
|
||||
|
@ -238,8 +239,12 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
|||
|
||||
fun registerTabcomplete(command2MC: ICommand2MC, commandNode: CoreCommandNode<Command2MCSender, *>, bukkitCommand: Command) {
|
||||
if (!CommodoreProvider.isSupported()) {
|
||||
if (ChromaUtils.isTest) {
|
||||
return
|
||||
} else {
|
||||
throw UnsupportedOperationException("Commodore is not supported! Please use 1.14 or higher. Server version: ${Bukkit.getVersion()}")
|
||||
}
|
||||
}
|
||||
// TODO: Allow extending annotation processing for methods and parameters
|
||||
val customTabCompleteMethods = command2MC.javaClass.declaredMethods
|
||||
.flatMap { method ->
|
||||
|
@ -316,5 +321,3 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private typealias CNode = CommandNode<Command2MCSender>
|
||||
|
|
|
@ -36,6 +36,13 @@ class CoreArgumentBuilder<S : Command2Sender, T>(
|
|||
)
|
||||
}
|
||||
|
||||
override fun then(argument: ArgumentBuilder<S, *>?): CoreArgumentBuilder<S, T> {
|
||||
if (argument is CoreArgumentBuilder<*, *>) {
|
||||
(argument as CoreArgumentBuilder<S, *>).data = data
|
||||
}
|
||||
return super.then(argument)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun <S : Command2Sender, T> argument(name: String, type: ArgumentType<T>, optional: Boolean): CoreArgumentBuilder<S, T> {
|
||||
return CoreArgumentBuilder(name, type, optional)
|
||||
|
|
|
@ -12,8 +12,8 @@ class CoreCommandNode<T : Command2Sender, TSD : NoOpSubcommandData>(
|
|||
literal: String,
|
||||
command: Command<T>,
|
||||
requirement: Predicate<T>,
|
||||
redirect: CommandNode<T>,
|
||||
modifier: RedirectModifier<T>,
|
||||
redirect: CommandNode<T>?,
|
||||
modifier: RedirectModifier<T>?,
|
||||
forks: Boolean,
|
||||
val data: TSD
|
||||
) : LiteralCommandNode<T>(literal, command, requirement, redirect, modifier, forks)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package buttondevteam.lib.chat.commands
|
||||
|
||||
import buttondevteam.core.MainPlugin
|
||||
import buttondevteam.lib.ChromaUtils
|
||||
import buttondevteam.lib.TBMCCoreAPI
|
||||
import buttondevteam.lib.chat.Command2Sender
|
||||
import buttondevteam.lib.chat.ICommand2
|
||||
|
@ -29,11 +30,9 @@ class CommandArgumentHelpManager<TC : ICommand2<TP>, TP : Command2Sender>(comman
|
|||
try {
|
||||
commandClass.getResourceAsStream("/commands.yml").use { str ->
|
||||
if (str == null) {
|
||||
TBMCCoreAPI.SendException(
|
||||
"Error while getting command data!",
|
||||
Exception("Resource not found!"),
|
||||
MainPlugin.instance
|
||||
)
|
||||
if (!ChromaUtils.isTest) {
|
||||
ChromaUtils.logWarn("Failed to get command data for $commandClass! No commands.yml file found.")
|
||||
}
|
||||
return@use
|
||||
}
|
||||
val config = YamlConfiguration.loadConfiguration(InputStreamReader(str))
|
||||
|
@ -56,7 +55,9 @@ class CommandArgumentHelpManager<TC : ICommand2<TP>, TP : Command2Sender>(comman
|
|||
fun getParameterHelpForMethod(method: Method): String? {
|
||||
val cs = commandConfig?.getConfigurationSection(method.name)
|
||||
if (cs == null) {
|
||||
if (!ChromaUtils.isTest) {
|
||||
MainPlugin.instance.logger.warning("Failed to get command data for $method! Make sure to use 'clean install' when building the project.")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
@ -28,19 +28,20 @@ object CommandUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Casts the node to whatever you say. Use responsibly.
|
||||
* Casts the node to whatever you say if it's a command node. Use responsibly. Returns null if an argument node.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <TP : Command2Sender, TSD : NoOpSubcommandData> CommandNode<TP>.core(): CoreCommandNode<TP, TSD> {
|
||||
return this as CoreCommandNode<TP, TSD>
|
||||
fun <TP : Command2Sender, TSD : NoOpSubcommandData> CommandNode<TP>.coreCommand(): CoreCommandNode<TP, TSD>? {
|
||||
return if (this is CoreCommandNode<*, *>) this as CoreCommandNode<TP, TSD>
|
||||
else null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node as an executable core command node or returns null if it's a no-op node.
|
||||
*/
|
||||
fun <TP : Command2Sender, TC : ICommand2<*>> CommandNode<TP>.coreExecutable(): CoreExecutableNode<TP, TC>? {
|
||||
val ret = core<TP, NoOpSubcommandData>()
|
||||
return if (ret.data is SubcommandData<*, *>) ret.core() else null
|
||||
val ret = this.coreCommand<TP, NoOpSubcommandData>()
|
||||
return if (ret?.data is SubcommandData<*, *>) ret.coreCommand() else null
|
||||
}
|
||||
|
||||
fun <TP : Command2Sender> CommandNode<TP>.coreArgument(): CoreArgumentCommandNode<TP, *>? {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package buttondevteam.lib.test
|
||||
|
||||
import net.milkbowl.vault.permission.Permission
|
||||
|
||||
class TestPermissions : Permission() {
|
||||
override fun getName(): String = "TestPermissions"
|
||||
|
||||
override fun isEnabled(): Boolean = true
|
||||
|
||||
override fun hasSuperPermsCompat(): Boolean = false
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun playerHas(world: String?, player: String?, permission: String?): Boolean = true
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun playerAdd(world: String?, player: String?, permission: String?): Boolean = true
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun playerRemove(world: String?, player: String?, permission: String?): Boolean = true
|
||||
|
||||
override fun groupHas(world: String?, group: String?, permission: String?): Boolean = true
|
||||
|
||||
override fun groupAdd(world: String?, group: String?, permission: String?): Boolean = true
|
||||
|
||||
override fun groupRemove(world: String?, group: String?, permission: String?): Boolean = true
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun playerInGroup(world: String?, player: String?, group: String?): Boolean = true
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun playerAddGroup(world: String?, player: String?, group: String?): Boolean = true
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun playerRemoveGroup(world: String?, player: String?, group: String?): Boolean = true
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getPlayerGroups(world: String?, player: String?): Array<String> = arrayOf()
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getPrimaryGroup(world: String?, player: String?): String = "default"
|
||||
|
||||
override fun getGroups(): Array<String> = arrayOf()
|
||||
|
||||
override fun hasGroupSupport(): Boolean = true
|
||||
}
|
Loading…
Reference in a new issue