diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt index 1859a00..030d58e 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt @@ -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 diff --git a/Chroma-Core/src/main/java/buttondevteam/core/TestPrepare.kt b/Chroma-Core/src/main/java/buttondevteam/core/TestPrepare.kt deleted file mode 100755 index 5223e23..0000000 --- a/Chroma-Core/src/main/java/buttondevteam/core/TestPrepare.kt +++ /dev/null @@ -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 }) - } -} diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/ScheduledServerRestartEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/ScheduledServerRestartEvent.kt index 4001bcd..44cd11e 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/ScheduledServerRestartEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/ScheduledServerRestartEvent.kt @@ -10,6 +10,7 @@ class ScheduledServerRestartEvent(val restartTicks: Int, val command: ScheduledR } companion object { + @JvmStatic val handlerList = HandlerList() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.kt index 1f16299..90537b7 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatEvent.kt @@ -54,6 +54,7 @@ class TBMCChatEvent( val isFromCommand get() = chatMessage.isFromCommand companion object { + @JvmStatic val handlerList = HandlerList() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatPreprocessEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatPreprocessEvent.kt index fcff4d6..906839f 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatPreprocessEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCChatPreprocessEvent.kt @@ -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() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt index 5be2115..5a3cd75 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt @@ -28,6 +28,7 @@ class TBMCCommandPreprocessEvent( override fun setCancelled(cancelled: Boolean) = run { this.cancelled = cancelled } companion object { + @JvmStatic val handlerList = HandlerList() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCExceptionEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCExceptionEvent.kt index 1be7908..81d60c5 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCExceptionEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCExceptionEvent.kt @@ -18,6 +18,7 @@ class TBMCExceptionEvent(val sourceMessage: String, val exception: Throwable) : } companion object { + @JvmStatic val handlerList = HandlerList() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt index 35bdd6b..c53ddf6 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCSystemChatEvent.kt @@ -56,6 +56,7 @@ class TBMCSystemChatEvent( } companion object { + @JvmStatic val handlerList = HandlerList() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt index 97cfdfc..2a07c44 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt @@ -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() diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt index e67f4b1..486af82 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt @@ -80,7 +80,7 @@ class ConfigData 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`") } } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt index 0df3877..e8da066 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.kt @@ -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, TP : Command2Sender>( */ private fun getExecutableNode(method: Method, command: TC, ann: Subcommand, remainingPath: String, argHelpManager: CommandArgumentHelpManager, fullPath: String): LiteralCommandNode { - val (params, _) = getCommandParametersAndSender(method, argHelpManager) // Param order is important + val (params, senderType) = getCommandParametersAndSender(method, argHelpManager) // Param order is important val paramMap = HashMap() 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 -> hasPermission(sender, data) }, method.annotations.filterNot { it is Subcommand }.toTypedArray(), @@ -364,9 +364,7 @@ abstract class Command2, TP : Command2Sender>( * @return A set of command node objects containing the commands */ val commandNodes: Set> - get() = dispatcher.root.children.stream() - .map { node: CommandNode -> node.core() } - .collect(Collectors.toUnmodifiableSet()) + get() = dispatcher.root.children.mapNotNull { it.coreCommand() }.toSet() /** * Get a node that belongs to the given command. @@ -375,7 +373,7 @@ abstract class Command2, TP : Command2Sender>( * @return A command node */ fun getCommandNode(command: String): CoreCommandNode? { // 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, TP : Command2Sender>( */ fun unregisterCommandIf(condition: Predicate>>, nested: Boolean) { dispatcher.root.children.removeIf { node -> node.coreExecutable()?.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, 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()?.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, TP : Command2Sender>( mainCommand: LiteralCommandNode, deep: Boolean = true ): List> { - return getSubcommands(deep, mainCommand.core()) + return mainCommand.coreCommand<_, NoOpSubcommandData>()?.let { getSubcommands(deep, it) } ?: emptyList() } private fun getSubcommands( @@ -425,6 +423,6 @@ abstract class Command2, TP : Command2Sender>( root: CoreNoOpNode ): List> { return root.children.mapNotNull { it.coreExecutable() } + - 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() } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt index 556f82a..14abeea 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt @@ -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,7 +239,11 @@ class Command2MC : Command2('/', true), Listener fun registerTabcomplete(command2MC: ICommand2MC, commandNode: CoreCommandNode, bukkitCommand: Command) { if (!CommodoreProvider.isSupported()) { - throw UnsupportedOperationException("Commodore is not supported! Please use 1.14 or higher. Server version: ${Bukkit.getVersion()}") + 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 @@ -316,5 +321,3 @@ class Command2MC : Command2('/', true), Listener } } } - -private typealias CNode = CommandNode diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreArgumentBuilder.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreArgumentBuilder.kt index e3c3f1e..7d0df65 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreArgumentBuilder.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreArgumentBuilder.kt @@ -36,6 +36,13 @@ class CoreArgumentBuilder( ) } + override fun then(argument: ArgumentBuilder?): CoreArgumentBuilder { + if (argument is CoreArgumentBuilder<*, *>) { + (argument as CoreArgumentBuilder).data = data + } + return super.then(argument) + } + companion object { fun argument(name: String, type: ArgumentType, optional: Boolean): CoreArgumentBuilder { return CoreArgumentBuilder(name, type, optional) diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreCommandNode.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreCommandNode.kt index a945a1d..7a2dd4a 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreCommandNode.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/CoreCommandNode.kt @@ -12,8 +12,8 @@ class CoreCommandNode( literal: String, command: Command, requirement: Predicate, - redirect: CommandNode, - modifier: RedirectModifier, + redirect: CommandNode?, + modifier: RedirectModifier?, forks: Boolean, val data: TSD ) : LiteralCommandNode(literal, command, requirement, redirect, modifier, forks) diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt index cb1621f..a57a9fc 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandArgumentHelpManager.kt @@ -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, 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, TP : Command2Sender>(comman fun getParameterHelpForMethod(method: Method): String? { val cs = commandConfig?.getConfigurationSection(method.name) if (cs == null) { - MainPlugin.instance.logger.warning("Failed to get command data for $method! Make sure to use 'clean install' when building the project.") + 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 } diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandUtils.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandUtils.kt index 21ba132..99dc49d 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandUtils.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/commands/CommandUtils.kt @@ -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 CommandNode.core(): CoreCommandNode { - return this as CoreCommandNode + fun CommandNode.coreCommand(): CoreCommandNode? { + return if (this is CoreCommandNode<*, *>) this as CoreCommandNode + else null } /** * Returns the node as an executable core command node or returns null if it's a no-op node. */ fun > CommandNode.coreExecutable(): CoreExecutableNode? { - val ret = core() - return if (ret.data is SubcommandData<*, *>) ret.core() else null + val ret = this.coreCommand() + return if (ret?.data is SubcommandData<*, *>) ret.coreCommand() else null } fun CommandNode.coreArgument(): CoreArgumentCommandNode? { diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/test/TestPermissions.kt b/Chroma-Core/src/main/java/buttondevteam/lib/test/TestPermissions.kt new file mode 100644 index 0000000..27270b0 --- /dev/null +++ b/Chroma-Core/src/main/java/buttondevteam/lib/test/TestPermissions.kt @@ -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 = arrayOf() + + @Deprecated("Deprecated in Java") + override fun getPrimaryGroup(world: String?, player: String?): String = "default" + + override fun getGroups(): Array = arrayOf() + + override fun hasGroupSupport(): Boolean = true +} \ No newline at end of file