diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt index 86df9c0..c397b5b 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.kt @@ -57,6 +57,11 @@ class MainPlugin : ButtonPlugin() { */ val prioritizeCustomCommands = iConfig.getData("prioritizeCustomCommands", false) + /** + * The permission group to use for players who are not in the server. + */ // TODO: Combine the channel access test with command permissions (with a generic implementation) + val externalPlayerPermissionGroup get() = iConfig.getData("externalPlayerPermissionGroup", "default") + public override fun pluginEnable() { instance = this val pdf = description diff --git a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt index 02d3925..a205029 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/PlayerListener.kt @@ -67,7 +67,7 @@ class PlayerListener(val plugin: MainPlugin) : Listener { private fun handlePreprocess(sender: CommandSender, message: String, event: Cancellable) { if (event.isCancelled) return val cg = ChromaGamerBase.getFromSender(sender) - val ev = TBMCCommandPreprocessEvent(cg, cg.channel.get(), message, sender) + val ev = TBMCCommandPreprocessEvent(cg, cg.channel.get(), message, cg) Bukkit.getPluginManager().callEvent(ev) if (ev.isCancelled) event.isCancelled = true //Cancel the original event } @@ -76,13 +76,7 @@ class PlayerListener(val plugin: MainPlugin) : Listener { fun onTBMCPreprocess(event: TBMCCommandPreprocessEvent) { if (event.isCancelled) return try { - val mcuser = event.sender.getAs(TBMCPlayerBase::class.java) - if (mcuser == null) { // TODO: The chat should continue to support unconnected accounts. - event.sender.sendMessage("You need to have your Minecraft account connected to send commands.") - event.isCancelled = true - return - } - val sender = Command2MCSender(mcuser, event.channel, event.permCheck) + val sender = Command2MCSender(event.sender, event.channel, event.permCheck) event.isCancelled = ButtonPlugin.command2MC.handleCommand(sender, event.message) } catch (e: Exception) { TBMCCoreAPI.SendException( diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/channel/Channel.kt b/Chroma-Core/src/main/java/buttondevteam/core/component/channel/Channel.kt index dbbfd95..0bc55a9 100755 --- a/Chroma-Core/src/main/java/buttondevteam/core/component/channel/Channel.kt +++ b/Chroma-Core/src/main/java/buttondevteam/core/component/channel/Channel.kt @@ -1,15 +1,12 @@ package buttondevteam.core.component.channel import buttondevteam.core.ComponentManager.get -import buttondevteam.core.MainPlugin import buttondevteam.lib.architecture.ConfigData import buttondevteam.lib.architecture.IHaveConfig import buttondevteam.lib.architecture.ListConfigData import buttondevteam.lib.chat.Color import buttondevteam.lib.player.ChromaGamerBase import org.bukkit.Bukkit -import org.bukkit.command.CommandSender -import org.bukkit.entity.Player import java.util.* import java.util.function.Function import java.util.function.Predicate @@ -45,7 +42,7 @@ open class Channel * Only those with access can see the messages. * If null, everyone has access. */ - private val filterAndErrorMSG: Function? + private val filterAndErrorMSG: Function? ) { private val config: IHaveConfig? = null // TODO: Use this @@ -188,28 +185,27 @@ open class Channel * @param permgroup The group that can access the channel or **null** to only allow OPs. * @return If has access */ - fun inGroupFilter(permgroup: String?): Function { - // TODO: This is Minecraft specific. Change all of this so it supports other ways of checking permissions. - // TODO: The commands have to be Minecraft specific, but the channels should be generic. - // TODO: Implement a way to check permissions for other platforms. Maybe specific strings, like "admin" or "mod"? - return noScoreResult( - { s -> - s.isOp || s is Player && permgroup?.let { pg -> - MainPlugin.permission.playerInGroup(s, pg) - } ?: false - }, - "You need to be a(n) " + (permgroup ?: "OP") + " to use this channel." - ) + @JvmStatic + fun inGroupFilter(permgroup: String?): Function { + return Function { it.checkChannelInGroup(permgroup) } } + @JvmStatic fun noScoreResult( - filter: Predicate, + filter: Predicate, errormsg: String? - ): Function { - return Function { s -> - if (filter.test(s)) RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) - else RecipientTestResult(errormsg) - } + ): Function { + return Function { noScoreResult(filter, errormsg, it) } + } + + @JvmStatic + fun noScoreResult( + filter: Predicate, + errormsg: String?, + user: ChromaGamerBase + ): RecipientTestResult { + return if (filter.test(user)) RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) + else RecipientTestResult(errormsg) } lateinit var globalChat: Channel diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt index 8ceeac3..5be2115 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/TBMCCommandPreprocessEvent.kt @@ -2,7 +2,6 @@ package buttondevteam.lib import buttondevteam.core.component.channel.Channel import buttondevteam.lib.player.ChromaGamerBase -import org.bukkit.command.CommandSender import org.bukkit.event.Cancellable import org.bukkit.event.Event import org.bukkit.event.HandlerList @@ -17,7 +16,7 @@ class TBMCCommandPreprocessEvent( val sender: ChromaGamerBase, val channel: Channel, val message: String, - val permCheck: CommandSender + val permCheck: ChromaGamerBase ) : Event(), Cancellable { private var cancelled = false override fun getHandlers(): HandlerList { 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 986446a..556f82a 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.kt @@ -59,7 +59,22 @@ class Command2MC : Command2('/', true), Listener } override fun hasPermission(sender: Command2MCSender, data: SubcommandData): Boolean { - if (sender.sender.isConsole) return true //Always allow the console + val defWorld = Bukkit.getWorlds().first().name + val check = if (sender.permCheck !is TBMCPlayerBase) ({ + MainPlugin.permission.groupHas( + defWorld, + MainPlugin.instance.externalPlayerPermissionGroup.get(), + it + ) + }) + else if (sender.permCheck.isConsole) ({ true }) //Always allow the console + else ({ perm: String -> + MainPlugin.permission.playerHas( + sender.permCheck.player?.location?.world?.name ?: defWorld, + sender.permCheck.offlinePlayer, + perm + ) + }) var p = true val cmdperm = "chroma.command.${data.fullPath.replace(' ', '.')}" @@ -71,11 +86,7 @@ class Command2MC : Command2('/', true), Listener for (perm in perms) { if (perm != null) { if (p) { //Use OfflinePlayer to avoid fetching player data - p = MainPlugin.permission.playerHas( - sender.sender.player?.location?.world?.name, - sender.sender.offlinePlayer, - perm - ) + p = check(perm) } else break //If any of the permissions aren't granted then don't allow } } @@ -113,14 +124,18 @@ class Command2MC : Command2('/', true), Listener if (original != null) { return original } - // Check Bukkit sender type - TODO: This is no longer the Bukkit sender type - if (senderType.isAssignableFrom(sender.sender.javaClass)) - return sender.sender + val cg = sender.sender + if (senderType.isAssignableFrom(cg.javaClass)) + return cg + // Check Bukkit sender type + if (cg is TBMCPlayerBase) { + if (senderType.isAssignableFrom(cg.offlinePlayer.javaClass)) return cg.offlinePlayer + if (cg.player?.javaClass?.let { senderType.isAssignableFrom(it) } == true) return cg.player + } //The command expects a user of our system if (ChromaGamerBase::class.java.isAssignableFrom(senderType)) { - val cg = sender.sender - if (cg.javaClass == senderType) - return cg + @Suppress("UNCHECKED_CAST") + return sender.sender.getAs(senderType as Class) } return null } @@ -187,7 +202,7 @@ class Command2MC : Command2('/', true), Listener val user = ChromaGamerBase.getFromSender(sender) // TODO: Senders should only be used for TBMCPlayerBase classes. ///trim(): remove space if there are no args handleCommand( - Command2MCSender(user as TBMCPlayerBase, user.channel.get(), sender), + Command2MCSender(user as TBMCPlayerBase, user.channel.get(), user), ("/${command.name} ${args.joinToString(" ")}").trim { it <= ' ' }, false ) return true diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt index 4016513..1b93455 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MCSender.kt @@ -1,10 +1,9 @@ package buttondevteam.lib.chat import buttondevteam.core.component.channel.Channel -import buttondevteam.lib.player.TBMCPlayerBase -import org.bukkit.command.CommandSender +import buttondevteam.lib.player.ChromaGamerBase -class Command2MCSender(val sender: TBMCPlayerBase, val channel: Channel, val permCheck: CommandSender) : Command2Sender { +class Command2MCSender(val sender: ChromaGamerBase, val channel: Channel, val permCheck: ChromaGamerBase) : Command2Sender { // TODO: Remove this class and only use the user classes. // TODO: The command context should be stored separately. override fun sendMessage(message: String) { diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt b/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt index b649c04..4ba7a3a 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.kt @@ -10,9 +10,9 @@ import buttondevteam.lib.TBMCChatEvent import buttondevteam.lib.TBMCChatPreprocessEvent import buttondevteam.lib.TBMCSystemChatEvent import buttondevteam.lib.TBMCSystemChatEvent.BroadcastTarget +import buttondevteam.lib.player.ChromaGamerBase import org.bukkit.Bukkit import org.bukkit.ChatColor -import org.bukkit.command.CommandSender import java.util.function.Supplier object TBMCChatAPI { @@ -38,7 +38,7 @@ object TBMCChatAPI { val rtr = getScoreOrSendError(channel, cm.permCheck) val score = rtr.score if (score == Channel.SCORE_SEND_NOPE || rtr.groupID == null) return@Supplier true - val eventPre = TBMCChatPreprocessEvent(cm.sender, channel, cm.message) + val eventPre = TBMCChatPreprocessEvent(cm.user, channel, cm.message) Bukkit.getPluginManager().callEvent(eventPre) if (eventPre.isCancelled) return@Supplier true cm.message = eventPre.message @@ -74,7 +74,7 @@ object TBMCChatAPI { return callEventAsync(event) } - private fun getScoreOrSendError(channel: Channel, sender: CommandSender): RecipientTestResult { + private fun getScoreOrSendError(channel: Channel, sender: ChromaGamerBase): RecipientTestResult { val result = channel.getRTR(sender) if (result.errormessage != null) sender.sendMessage("${ChatColor.RED}" + result.errormessage) return result diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt index 87bd990..b2355fd 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/ChromaGamerBase.kt @@ -167,6 +167,13 @@ abstract class ChromaGamerBase : Command2Sender { .findAny().orElseThrow { RuntimeException("Channel $id not found!") } }, { ch -> ch.identifier }) + /** + * Check channel access by checking if the user is in the given group. If the group is null, check if the user is OP. + * + * Note that these groups originally come from Minecraft. + */ // TODO: Allow if a connected account has access + abstract fun checkChannelInGroup(group: String?): Channel.RecipientTestResult + companion object { private const val TBMC_PLAYERS_DIR = "TBMC/players/" private val senderConverters = ArrayList>>() diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt index 6ed100b..5c0871b 100755 --- a/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.kt @@ -1,5 +1,7 @@ package buttondevteam.lib.player +import buttondevteam.core.MainPlugin +import buttondevteam.core.component.channel.Channel import buttondevteam.lib.architecture.IHaveConfig import org.bukkit.Bukkit import org.bukkit.entity.Player @@ -45,7 +47,6 @@ abstract class TBMCPlayerBase : ChromaGamerBase() { } override fun sendMessage(message: String) { - // TODO: Random senders (Discord) won't receive messages. Including when trying to chat. player?.sendMessage(message) } @@ -57,6 +58,18 @@ abstract class TBMCPlayerBase : ChromaGamerBase() { return playerName.get() } + override fun checkChannelInGroup(group: String?): Channel.RecipientTestResult { + return Channel.noScoreResult( + { s -> + s is TBMCPlayerBase && (s.offlinePlayer.isOp || s.player != null && group?.let { pg -> + MainPlugin.permission.playerInGroup(s.player, pg) + } ?: false) + }, + "You need to be a(n) ${group ?: "OP"} to use this channel.", + this + ) + } + companion object { /** * Get player as a plugin player.