Only use Chroma users for chat messages

- Don't use Command2Sender for getting Chroma users
- The CommandSender interface is a Minecraft-specific concept and using Command2Sender just adds unnecessary complexity
- Added convenience methods for getting TBMC players and the console
This commit is contained in:
Norbi Peti 2023-05-23 00:49:52 +02:00
parent b57420c72a
commit 291fc068fd
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
15 changed files with 126 additions and 119 deletions

View file

@ -83,7 +83,7 @@ class MainPlugin : ButtonPlugin() {
ChromaGamerBase.addConverter { commandSender: CommandSender -> ChromaGamerBase.addConverter { commandSender: CommandSender ->
Optional.ofNullable( Optional.ofNullable(
if (commandSender is ConsoleCommandSender || commandSender is BlockCommandSender) if (commandSender is ConsoleCommandSender || commandSender is BlockCommandSender)
TBMCPlayerBase.getPlayer(UUID(0, 0), TBMCPlayer::class.java) TBMCPlayerBase.getConsole()
else null else null
) )
} }

View file

@ -1,6 +1,9 @@
package buttondevteam.core package buttondevteam.core
import buttondevteam.lib.* import buttondevteam.lib.TBMCChatEvent
import buttondevteam.lib.TBMCCommandPreprocessEvent
import buttondevteam.lib.TBMCCoreAPI
import buttondevteam.lib.TBMCSystemChatEvent
import buttondevteam.lib.architecture.ButtonPlugin import buttondevteam.lib.architecture.ButtonPlugin
import buttondevteam.lib.chat.ChatMessage import buttondevteam.lib.chat.ChatMessage
import buttondevteam.lib.chat.Command2MCSender import buttondevteam.lib.chat.Command2MCSender
@ -8,9 +11,9 @@ import buttondevteam.lib.chat.TBMCChatAPI
import buttondevteam.lib.player.ChromaGamerBase import buttondevteam.lib.player.ChromaGamerBase
import buttondevteam.lib.player.TBMCPlayer import buttondevteam.lib.player.TBMCPlayer
import buttondevteam.lib.player.TBMCPlayerBase import buttondevteam.lib.player.TBMCPlayerBase
import buttondevteam.lib.player.TBMCPlayerBase.Companion.asTBMC
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.event.Cancellable import org.bukkit.event.Cancellable
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority import org.bukkit.event.EventPriority
@ -45,8 +48,9 @@ class PlayerListener(val plugin: MainPlugin) : Listener {
fun onSystemChat(event: TBMCSystemChatEvent) { fun onSystemChat(event: TBMCSystemChatEvent) {
if (event.isHandled) return if (event.isHandled) return
if (event.exceptions.any { "Minecraft".equals(it, ignoreCase = true) }) return if (event.exceptions.any { "Minecraft".equals(it, ignoreCase = true) }) return
Bukkit.getOnlinePlayers().stream().filter { sender: CommandSender -> event.shouldSendTo(sender) } Bukkit.getOnlinePlayers().stream().filter { event.shouldSendTo(it.asTBMC()) }
.forEach { p: Player -> p.sendMessage(event.channel.displayName.get().substring(0, 2) + event.message) } .forEach { it.sendMessage(event.channel.displayName.get().substring(0, 2) + event.message) }
// TODO: Replace the substring call with a proper color code getter.
} }
@EventHandler @EventHandler
@ -63,8 +67,7 @@ class PlayerListener(val plugin: MainPlugin) : Listener {
private fun handlePreprocess(sender: CommandSender, message: String, event: Cancellable) { private fun handlePreprocess(sender: CommandSender, message: String, event: Cancellable) {
if (event.isCancelled) return if (event.isCancelled) return
val cg = ChromaGamerBase.getFromSender(sender) val cg = ChromaGamerBase.getFromSender(sender)
?: throw RuntimeException("Couldn't get user from sender for " + sender.name + "!") val ev = TBMCCommandPreprocessEvent(cg, cg.channel.get(), message, sender)
val ev = TBMCCommandPreprocessEvent(sender, cg.channel.get(), message, sender)
Bukkit.getPluginManager().callEvent(ev) Bukkit.getPluginManager().callEvent(ev)
if (ev.isCancelled) event.isCancelled = true //Cancel the original event if (ev.isCancelled) event.isCancelled = true //Cancel the original event
} }
@ -73,7 +76,13 @@ class PlayerListener(val plugin: MainPlugin) : Listener {
fun onTBMCPreprocess(event: TBMCCommandPreprocessEvent) { fun onTBMCPreprocess(event: TBMCCommandPreprocessEvent) {
if (event.isCancelled) return if (event.isCancelled) return
try { try {
val sender = Command2MCSender(event.sender, event.channel, event.permCheck) 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)
event.isCancelled = ButtonPlugin.command2MC.handleCommand(sender, event.message) event.isCancelled = ButtonPlugin.command2MC.handleCommand(sender, event.message)
} catch (e: Exception) { } catch (e: Exception) {
TBMCCoreAPI.SendException( TBMCCoreAPI.SendException(
@ -88,7 +97,7 @@ class PlayerListener(val plugin: MainPlugin) : Listener {
fun onPlayerChat(event: AsyncPlayerChatEvent) { fun onPlayerChat(event: AsyncPlayerChatEvent) {
if (event.isCancelled) return //The chat plugin should cancel it after this handler if (event.isCancelled) return //The chat plugin should cancel it after this handler
val cp = TBMCPlayerBase.getPlayer(event.player.uniqueId, TBMCPlayer::class.java) val cp = TBMCPlayerBase.getPlayer(event.player.uniqueId, TBMCPlayer::class.java)
TBMCChatAPI.sendChatMessage(ChatMessage.builder(event.player, cp, event.message).build()) TBMCChatAPI.sendChatMessage(ChatMessage.builder(cp, event.message).build())
//Not cancelling the original event here, it's cancelled in the chat plugin //Not cancelling the original event here, it's cancelled in the chat plugin
//This way other plugins can deal with the MC formatting if the chat plugin isn't present, but other platforms still get the message //This way other plugins can deal with the MC formatting if the chat plugin isn't present, but other platforms still get the message
} }
@ -102,9 +111,9 @@ class PlayerListener(val plugin: MainPlugin) : Listener {
val msg = plugin.chatFormat.get() val msg = plugin.chatFormat.get()
.replace("{channel}", channel.displayName.get()) .replace("{channel}", channel.displayName.get())
.replace("{origin}", event.origin.substring(0, 1)) .replace("{origin}", event.origin.substring(0, 1))
.replace("{name}", ChromaUtils.getDisplayName(event.sender)) .replace("{name}", event.user.name)
.replace("{message}", String.format("§%x%s", channel.color.get().ordinal, event.message)) .replace("{message}", String.format("§%x%s", channel.color.get().ordinal, event.message))
for (player in Bukkit.getOnlinePlayers()) if (event.shouldSendTo(player)) player.sendMessage(msg) for (player in Bukkit.getOnlinePlayers()) if (event.shouldSendTo(player.asTBMC())) player.sendMessage(msg)
Bukkit.getConsoleSender().sendMessage(msg) Bukkit.getConsoleSender().sendMessage(msg)
} }
} }

View file

@ -6,6 +6,7 @@ import buttondevteam.lib.architecture.ConfigData
import buttondevteam.lib.architecture.IHaveConfig import buttondevteam.lib.architecture.IHaveConfig
import buttondevteam.lib.architecture.ListConfigData import buttondevteam.lib.architecture.ListConfigData
import buttondevteam.lib.chat.Color import buttondevteam.lib.chat.Color
import buttondevteam.lib.player.ChromaGamerBase
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.entity.Player import org.bukkit.entity.Player
@ -75,14 +76,14 @@ open class Channel
* @param sender The user we're sending to * @param sender The user we're sending to
* @param score The (source) score to compare with the user's * @param score The (source) score to compare with the user's
*/ */
fun shouldSendTo(sender: CommandSender, score: Int): Boolean { fun shouldSendTo(sender: ChromaGamerBase, score: Int): Boolean {
return score == getMCScore(sender) //If there's any error, the score won't be equal return score == getMCScore(sender) //If there's any error, the score won't be equal
} }
/** /**
* Note: Errors are sent to the sender automatically * Note: Errors are sent to the sender automatically
*/ */
fun getMCScore(sender: CommandSender): Int { fun getMCScore(sender: ChromaGamerBase): Int {
return getRTR(sender).score //No need to check if there was an error return getRTR(sender).score //No need to check if there was an error
} }
@ -91,11 +92,11 @@ open class Channel
* *
* Null means don't send * Null means don't send
*/ */
fun getGroupID(sender: CommandSender): String? { fun getGroupID(sender: ChromaGamerBase): String? {
return getRTR(sender).groupID //No need to check if there was an error return getRTR(sender).groupID //No need to check if there was an error
} }
fun getRTR(sender: CommandSender): RecipientTestResult { fun getRTR(sender: ChromaGamerBase): RecipientTestResult {
return filterAndErrorMSG?.apply(sender) ?: RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) return filterAndErrorMSG?.apply(sender) ?: RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE)
} }
@ -188,13 +189,13 @@ open class Channel
* @return If has access * @return If has access
*/ */
fun inGroupFilter(permgroup: String?): Function<CommandSender, RecipientTestResult> { fun inGroupFilter(permgroup: String?): Function<CommandSender, RecipientTestResult> {
// 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( return noScoreResult(
{ s -> { s ->
s.isOp || s is Player && permgroup?.let { pg -> s.isOp || s is Player && permgroup?.let { pg ->
MainPlugin.permission?.playerInGroup( MainPlugin.permission.playerInGroup(s, pg)
s,
pg
)
} ?: false } ?: false
}, },
"You need to be a(n) " + (permgroup ?: "OP") + " to use this channel." "You need to be a(n) " + (permgroup ?: "OP") + " to use this channel."

View file

@ -5,7 +5,6 @@ import buttondevteam.lib.TBMCSystemChatEvent.BroadcastTarget
import buttondevteam.lib.architecture.Component import buttondevteam.lib.architecture.Component
import buttondevteam.lib.chat.* import buttondevteam.lib.chat.*
import buttondevteam.lib.chat.Command2.* import buttondevteam.lib.chat.Command2.*
import buttondevteam.lib.player.ChromaGamerBase
import org.bukkit.ChatColor import org.bukkit.ChatColor
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
@ -39,22 +38,17 @@ class ChannelComponent : Component<JavaPlugin>() {
@Subcommand @Subcommand
fun def(senderMC: Command2MCSender, @OptionalArg @TextArg message: String?) { fun def(senderMC: Command2MCSender, @OptionalArg @TextArg message: String?) {
val sender = senderMC.sender val user = senderMC.sender
val user = ChromaGamerBase.getFromSender(sender)
if (user == null) {
sender.sendMessage("${ChatColor.RED}You can't use channels from this platform.")
return
}
if (message == null) { if (message == null) {
val oldch = user.channel.get() val oldch = user.channel.get()
if (oldch is ChatRoom) oldch.leaveRoom(sender) if (oldch is ChatRoom) oldch.leaveRoom(user)
if (oldch == channel) user.channel.set(Channel.globalChat) else { if (oldch == channel) user.channel.set(Channel.globalChat) else {
user.channel.set(channel) user.channel.set(channel)
if (channel is ChatRoom) channel.joinRoom(sender) if (channel is ChatRoom) channel.joinRoom(user)
} }
sender.sendMessage("${ChatColor.GOLD}You are now talking in: ${ChatColor.AQUA}" + user.channel.get().displayName.get()) user.sendMessage("${ChatColor.GOLD}You are now talking in: ${ChatColor.AQUA}" + user.channel.get().displayName.get())
} else TBMCChatAPI.sendChatMessage( } else TBMCChatAPI.sendChatMessage(
ChatMessage.builder(sender, user, message).fromCommand(true) ChatMessage.builder(user, message).fromCommand(true)
.permCheck(senderMC.permCheck).build(), channel .permCheck(senderMC.permCheck).build(), channel
) )
} }

View file

@ -3,17 +3,17 @@ package buttondevteam.core.component.channel
import buttondevteam.lib.TBMCSystemChatEvent import buttondevteam.lib.TBMCSystemChatEvent
import buttondevteam.lib.chat.Color import buttondevteam.lib.chat.Color
import buttondevteam.lib.chat.TBMCChatAPI import buttondevteam.lib.chat.TBMCChatAPI
import org.bukkit.command.CommandSender import buttondevteam.lib.player.ChromaGamerBase
class ChatRoom(displayname: String, color: Color, command: String) : Channel( class ChatRoom(displayname: String, color: Color, command: String) : Channel(
displayname, color, command, null // TODO: Custom filter for rooms using abstract method displayname, color, command, null // TODO: Custom filter for rooms using abstract method
) { ) {
private val usersInRoom: MutableList<CommandSender> = ArrayList() private val usersInRoom: MutableList<ChromaGamerBase> = ArrayList()
private fun isInRoom(sender: CommandSender): Boolean { private fun isInRoom(sender: ChromaGamerBase): Boolean {
return usersInRoom.contains(sender) return usersInRoom.contains(sender)
} }
fun joinRoom(sender: CommandSender) { fun joinRoom(sender: ChromaGamerBase) {
usersInRoom.add(sender) usersInRoom.add(sender)
TBMCChatAPI.SendSystemMessage( TBMCChatAPI.SendSystemMessage(
this, this,
@ -23,7 +23,7 @@ class ChatRoom(displayname: String, color: Color, command: String) : Channel(
) //Always show message in the same kind of channel ) //Always show message in the same kind of channel
} }
fun leaveRoom(sender: CommandSender) { fun leaveRoom(sender: ChromaGamerBase) {
usersInRoom.remove(sender) usersInRoom.remove(sender)
TBMCChatAPI.SendSystemMessage( TBMCChatAPI.SendSystemMessage(
this, this,

View file

@ -10,6 +10,7 @@ import java.util.function.Supplier
object ChromaUtils { object ChromaUtils {
@JvmStatic @JvmStatic
@Deprecated("Use ChromaGamingBase.name", ReplaceWith("ChromaGamerBase.getFromSender(sender).name"))
fun getDisplayName(sender: CommandSender): String { fun getDisplayName(sender: CommandSender): String {
return when (sender) { return when (sender) {
is IHaveFancyName -> sender.fancyName is IHaveFancyName -> sender.fancyName

View file

@ -4,7 +4,6 @@ import buttondevteam.core.component.channel.Channel
import buttondevteam.core.component.channel.Channel.RecipientTestResult import buttondevteam.core.component.channel.Channel.RecipientTestResult
import buttondevteam.lib.chat.ChatMessage import buttondevteam.lib.chat.ChatMessage
import buttondevteam.lib.player.ChromaGamerBase import buttondevteam.lib.player.ChromaGamerBase
import org.bukkit.command.CommandSender
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
/** /**
@ -14,40 +13,44 @@ import org.bukkit.event.HandlerList
*/ */
class TBMCChatEvent( class TBMCChatEvent(
channel: Channel, channel: Channel,
public val chatMessage: ChatMessage, val chatMessage: ChatMessage,
rtr: RecipientTestResult rtr: RecipientTestResult
) : TBMCChatEventBase(channel, chatMessage.message, rtr.score, rtr.groupID!!) { ) : TBMCChatEventBase(channel, chatMessage.message, rtr.score, rtr.groupID!!) {
private val isIgnoreSenderPermissions: Boolean get() = chatMessage.permCheck !== chatMessage.sender private val isIgnoreSenderPermissions: Boolean get() = chatMessage.permCheck !== chatMessage.user
/** /**
* This will allow the sender of the message if [.isIgnoreSenderPermissions] is true. * This will allow the sender of the message if [.isIgnoreSenderPermissions] is true.
*/ */
override fun shouldSendTo(sender: CommandSender): Boolean { override fun shouldSendTo(sender: ChromaGamerBase): Boolean {
return if (isIgnoreSenderPermissions && sender == chatMessage.sender) true else super.shouldSendTo(sender) //Allow sending the message no matter what return if (isIgnoreSenderPermissions && sender == chatMessage.user) true else super.shouldSendTo(sender) //Allow sending the message no matter what
} }
/** /**
* This will allow the sender of the message if [.isIgnoreSenderPermissions] is true. * This will allow the sender of the message if [.isIgnoreSenderPermissions] is true.
*/ */
override fun getMCScore(sender: CommandSender): Int { override fun getMCScore(sender: ChromaGamerBase): Int {
return if (isIgnoreSenderPermissions && sender == chatMessage.sender) score else super.getMCScore(sender) //Send in the correct group no matter what return if (isIgnoreSenderPermissions && sender == chatMessage.user) score else super.getMCScore(sender) //Send in the correct group no matter what
} }
/** /**
* This will allow the sender of the message if [.isIgnoreSenderPermissions] is true. * This will allow the sender of the message if [.isIgnoreSenderPermissions] is true.
*/ */
override fun getGroupID(sender: CommandSender): String? { override fun getGroupID(sender: ChromaGamerBase): String? {
return if (isIgnoreSenderPermissions && sender == chatMessage.sender) groupID else super.getGroupID(sender) //Send in the correct group no matter what return if (isIgnoreSenderPermissions && sender == chatMessage.user) groupID else super.getGroupID(sender) //Send in the correct group no matter what
} }
override fun getHandlers(): HandlerList { override fun getHandlers(): HandlerList {
return handlerList return handlerList
} }
val sender: CommandSender get() = chatMessage.sender /** @see ChatMessage.user */
val user: ChromaGamerBase get() = chatMessage.user val user: ChromaGamerBase get() = chatMessage.user
/** @see ChatMessage.origin */
val origin: String get() = chatMessage.origin val origin: String get() = chatMessage.origin
/** @see ChatMessage.isFromCommand */
val isFromCommand get() = chatMessage.isFromCommand val isFromCommand get() = chatMessage.isFromCommand
companion object { companion object {

View file

@ -1,7 +1,7 @@
package buttondevteam.lib package buttondevteam.lib
import buttondevteam.core.component.channel.Channel import buttondevteam.core.component.channel.Channel
import org.bukkit.command.CommandSender import buttondevteam.lib.player.ChromaGamerBase
import org.bukkit.event.Cancellable import org.bukkit.event.Cancellable
import org.bukkit.event.Event import org.bukkit.event.Event
@ -23,14 +23,14 @@ abstract class TBMCChatEventBase(
/** /**
* Note: Errors are sent to the sender automatically * Note: Errors are sent to the sender automatically
*/ */
open fun shouldSendTo(sender: CommandSender): Boolean { open fun shouldSendTo(sender: ChromaGamerBase): Boolean {
return channel.shouldSendTo(sender, score) return channel.shouldSendTo(sender, score)
} }
/** /**
* Note: Errors are sent to the sender automatically * Note: Errors are sent to the sender automatically
*/ */
open fun getMCScore(sender: CommandSender): Int { open fun getMCScore(sender: ChromaGamerBase): Int {
return channel.getMCScore(sender) return channel.getMCScore(sender)
} }
@ -39,7 +39,7 @@ abstract class TBMCChatEventBase(
* *
* Null means don't send * Null means don't send
*/ */
open fun getGroupID(sender: CommandSender): String? { open fun getGroupID(sender: ChromaGamerBase): String? {
return channel.getGroupID(sender) return channel.getGroupID(sender)
} }

View file

@ -1,6 +1,7 @@
package buttondevteam.lib package buttondevteam.lib
import buttondevteam.core.component.channel.Channel import buttondevteam.core.component.channel.Channel
import buttondevteam.lib.player.ChromaGamerBase
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.event.Cancellable import org.bukkit.event.Cancellable
import org.bukkit.event.Event import org.bukkit.event.Event
@ -13,7 +14,7 @@ import org.bukkit.event.HandlerList
* @author NorbiPeti * @author NorbiPeti
*/ */
class TBMCCommandPreprocessEvent( class TBMCCommandPreprocessEvent(
val sender: CommandSender, val sender: ChromaGamerBase,
val channel: Channel, val channel: Channel,
val message: String, val message: String,
val permCheck: CommandSender val permCheck: CommandSender

View file

@ -1,16 +1,11 @@
package buttondevteam.lib.chat package buttondevteam.lib.chat
import buttondevteam.lib.player.ChromaGamerBase import buttondevteam.lib.player.ChromaGamerBase
import org.bukkit.command.CommandSender
import java.util.* import java.util.*
class ChatMessage internal constructor( class ChatMessage internal constructor(
/** /**
* The sender which sends the message. * The Chroma user who sent the message.
*/
val sender: Command2Sender,
/**
* The Chroma user which sends the message.
*/ */
val user: ChromaGamerBase, val user: ChromaGamerBase,
/** /**
@ -24,7 +19,7 @@ class ChatMessage internal constructor(
/** /**
* The sender which we should check for permissions. Same as [.sender] by default. * The sender which we should check for permissions. Same as [.sender] by default.
*/ */
val permCheck: CommandSender, val permCheck: ChromaGamerBase,
/** /**
* The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user. * The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user.
* *
@ -34,20 +29,19 @@ class ChatMessage internal constructor(
) { ) {
class ChatMessageBuilder internal constructor( class ChatMessageBuilder internal constructor(
private var sender: CommandSender,
private var user: ChromaGamerBase, private var user: ChromaGamerBase,
private var message: String, private var message: String,
private var origin: String private var origin: String
) { ) {
private var fromCommand = false private var fromCommand = false
private var permCheck: CommandSender? = null private var permCheck: ChromaGamerBase? = null
fun fromCommand(fromCommand: Boolean): ChatMessageBuilder { fun fromCommand(fromCommand: Boolean): ChatMessageBuilder {
this.fromCommand = fromCommand this.fromCommand = fromCommand
return this return this
} }
fun permCheck(permCheck: CommandSender): ChatMessageBuilder { fun permCheck(permCheck: ChromaGamerBase): ChatMessageBuilder {
this.permCheck = permCheck this.permCheck = permCheck
return this return this
} }
@ -58,20 +52,20 @@ class ChatMessage internal constructor(
} }
fun build(): ChatMessage { fun build(): ChatMessage {
return ChatMessage(sender, user, message, fromCommand, permCheck ?: sender, origin) return ChatMessage(user, message, fromCommand, permCheck ?: user, origin)
} }
override fun toString(): String { override fun toString(): String {
return "ChatMessage.ChatMessageBuilder(sender=$sender, user=$user, message=$message, fromCommand=$fromCommand, permCheck=$permCheck, origin=$origin)" return "ChatMessage.ChatMessageBuilder(user=$user, message=$message, fromCommand=$fromCommand, permCheck=$permCheck, origin=$origin)"
} }
} }
companion object { companion object {
@JvmStatic @JvmStatic
fun builder(sender: CommandSender, user: ChromaGamerBase, message: String): ChatMessageBuilder { fun builder(user: ChromaGamerBase, message: String): ChatMessageBuilder {
return ChatMessageBuilder( return ChatMessageBuilder(
sender, user, message, user, message,
user.folder.substring(0, 1).uppercase(Locale.getDefault()) + user.folder.substring(1) user.folder.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
) )
} }
} }

View file

@ -10,6 +10,7 @@ import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
import buttondevteam.lib.chat.commands.MCCommandSettings import buttondevteam.lib.chat.commands.MCCommandSettings
import buttondevteam.lib.chat.commands.SubcommandData import buttondevteam.lib.chat.commands.SubcommandData
import buttondevteam.lib.player.ChromaGamerBase import buttondevteam.lib.player.ChromaGamerBase
import buttondevteam.lib.player.TBMCPlayerBase
import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.builder.LiteralArgumentBuilder.literal import com.mojang.brigadier.builder.LiteralArgumentBuilder.literal
import com.mojang.brigadier.builder.RequiredArgumentBuilder import com.mojang.brigadier.builder.RequiredArgumentBuilder
@ -21,9 +22,7 @@ import me.lucko.commodore.CommodoreProvider
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.ChatColor import org.bukkit.ChatColor
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.OfflinePlayer
import org.bukkit.command.* import org.bukkit.command.*
import org.bukkit.entity.Player
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.permissions.Permission import org.bukkit.permissions.Permission
import org.bukkit.permissions.PermissionDefault import org.bukkit.permissions.PermissionDefault
@ -60,8 +59,7 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
} }
override fun hasPermission(sender: Command2MCSender, data: SubcommandData<ICommand2MC, Command2MCSender>): Boolean { override fun hasPermission(sender: Command2MCSender, data: SubcommandData<ICommand2MC, Command2MCSender>): Boolean {
val mcsender = sender.sender if (sender.sender.isConsole) return true //Always allow the console
if (mcsender is ConsoleCommandSender) return true //Always allow the console
var p = true var p = true
val cmdperm = "chroma.command.${data.fullPath.replace(' ', '.')}" val cmdperm = "chroma.command.${data.fullPath.replace(' ', '.')}"
@ -73,12 +71,11 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
for (perm in perms) { for (perm in perms) {
if (perm != null) { if (perm != null) {
if (p) { //Use OfflinePlayer to avoid fetching player data if (p) { //Use OfflinePlayer to avoid fetching player data
p = if (mcsender is OfflinePlayer) MainPlugin.permission.playerHas( p = MainPlugin.permission.playerHas(
if (mcsender is Player) mcsender.location.world?.name else null, sender.sender.player?.location?.world?.name,
mcsender as OfflinePlayer, sender.sender.offlinePlayer,
perm perm
) else false //Use sender's method )
if (!p) p = mcsender.hasPermission(perm)
} else break //If any of the permissions aren't granted then don't allow } else break //If any of the permissions aren't granted then don't allow
} }
} }
@ -116,13 +113,13 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
if (original != null) { if (original != null) {
return original return original
} }
// Check Bukkit sender type // Check Bukkit sender type - TODO: This is no longer the Bukkit sender type
if (senderType.isAssignableFrom(sender.sender.javaClass)) if (senderType.isAssignableFrom(sender.sender.javaClass))
return sender.sender return sender.sender
//The command expects a user of our system //The command expects a user of our system
if (ChromaGamerBase::class.java.isAssignableFrom(senderType)) { if (ChromaGamerBase::class.java.isAssignableFrom(senderType)) {
val cg = ChromaGamerBase.getFromSender(sender.sender) val cg = sender.sender
if (cg?.javaClass == senderType) if (cg.javaClass == senderType)
return cg return cg
} }
return null return null
@ -187,18 +184,10 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
} }
private fun executeCommand(sender: CommandSender, command: Command, label: String, args: Array<String>): Boolean { private fun executeCommand(sender: CommandSender, command: Command, label: String, args: Array<String>): Boolean {
val user = ChromaGamerBase.getFromSender(sender) val user = ChromaGamerBase.getFromSender(sender) // TODO: Senders should only be used for TBMCPlayerBase classes.
if (user == null) {
TBMCCoreAPI.SendException(
"Failed to run Bukkit command for user!",
Throwable("No Chroma user found"),
MainPlugin.instance
)
sender.sendMessage("${ChatColor.RED}An internal error occurred.")
return true
}
///trim(): remove space if there are no args ///trim(): remove space if there are no args
handleCommand(Command2MCSender(sender, user.channel.get(), sender), handleCommand(
Command2MCSender(user as TBMCPlayerBase, user.channel.get(), sender),
("/${command.name} ${args.joinToString(" ")}").trim { it <= ' ' }, false ("/${command.name} ${args.joinToString(" ")}").trim { it <= ' ' }, false
) )
return true return true

View file

@ -1,16 +1,18 @@
package buttondevteam.lib.chat package buttondevteam.lib.chat
import buttondevteam.core.component.channel.Channel import buttondevteam.core.component.channel.Channel
import buttondevteam.lib.player.TBMCPlayerBase
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
class Command2MCSender(val sender: CommandSender, val channel: Channel, val permCheck: CommandSender) : Command2Sender { class Command2MCSender(val sender: TBMCPlayerBase, val channel: Channel, val permCheck: CommandSender) : Command2Sender {
// TODO: Remove this class and only use the user classes.
// TODO: The command context should be stored separately.
override fun sendMessage(message: String) { override fun sendMessage(message: String) {
sender.sendMessage(message) sender.sendMessage(message)
} }
override fun sendMessage(message: Array<String>) { override fun sendMessage(message: Array<String>) {
sender.sendMessage(*message) sender.sendMessage(message)
} }
override fun getName(): String { override fun getName(): String {

View file

@ -28,11 +28,10 @@ object TBMCChatAPI {
@JvmOverloads @JvmOverloads
@JvmStatic @JvmStatic
fun sendChatMessage(cm: ChatMessage, channel: Channel = cm.user.channel.get()): Boolean { fun sendChatMessage(cm: ChatMessage, channel: Channel = cm.user.channel.get()): Boolean {
if (!channelList.contains(channel)) throw RuntimeException( if (!channelList.contains(channel))
"Channel " + channel.displayName.get() + " not registered!" throw RuntimeException("Channel ${channel.displayName.get()} not registered!")
)
if (!channel.isEnabled.get()) { if (!channel.isEnabled.get()) {
cm.sender.sendMessage("${ChatColor.RED}The channel '${channel.displayName.get()}' is disabled!") cm.user.sendMessage("${ChatColor.RED}The channel '${channel.displayName.get()}' is disabled!")
return true //Cancel sending if channel is disabled return true //Cancel sending if channel is disabled
} }
val task = Supplier { val task = Supplier {

View file

@ -7,7 +7,6 @@ import buttondevteam.lib.TBMCCoreAPI
import buttondevteam.lib.architecture.ConfigData import buttondevteam.lib.architecture.ConfigData
import buttondevteam.lib.architecture.ConfigData.Companion.saveNow import buttondevteam.lib.architecture.ConfigData.Companion.saveNow
import buttondevteam.lib.architecture.IHaveConfig import buttondevteam.lib.architecture.IHaveConfig
import buttondevteam.lib.chat.Command2MCSender
import buttondevteam.lib.chat.Command2Sender import buttondevteam.lib.chat.Command2Sender
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
@ -18,7 +17,7 @@ import java.util.function.Function
import java.util.function.Supplier import java.util.function.Supplier
@ChromaGamerEnforcer @ChromaGamerEnforcer
abstract class ChromaGamerBase { abstract class ChromaGamerBase : Command2Sender {
lateinit var config: IHaveConfig lateinit var config: IHaveConfig
protected set protected set
@ -104,9 +103,9 @@ abstract class ChromaGamerBase {
} }
/** /**
* Returns the ID for the T typed player object connected with this one or null if no connection found. * Returns the ID for the given user type folder connected with this one or null if no connection found.
* *
* @param cl The player class to get the ID from * @param folder The player type folder to get the ID from
* @return The ID or null if not found * @return The ID or null if not found
*/ */
fun getConnectedID(folder: String): String? { fun getConnectedID(folder: String): String? {
@ -170,7 +169,7 @@ abstract class ChromaGamerBase {
companion object { companion object {
private const val TBMC_PLAYERS_DIR = "TBMC/players/" private const val TBMC_PLAYERS_DIR = "TBMC/players/"
private val senderConverters = ArrayList<Function<Command2Sender, out Optional<out ChromaGamerBase>>>() private val senderConverters = ArrayList<Function<CommandSender, out Optional<out ChromaGamerBase>>>()
/** /**
* Holds data per user class * Holds data per user class
@ -305,12 +304,7 @@ abstract class ChromaGamerBase {
*/ */
@JvmStatic @JvmStatic
fun addConverter(converter: Function<CommandSender, Optional<out ChromaGamerBase>>) { fun addConverter(converter: Function<CommandSender, Optional<out ChromaGamerBase>>) {
senderConverters.add(0) { sender -> senderConverters.add(0, converter)
when (sender) {
is Command2MCSender -> converter.apply(sender.sender)
else -> Optional.empty()
}
}
} }
/** /**
@ -321,20 +315,7 @@ abstract class ChromaGamerBase {
* @return A user as returned by a converter * @return A user as returned by a converter
*/ */
@JvmStatic @JvmStatic
@Deprecated("Use Command2Sender instead", ReplaceWith("getFromSender(Command2MCSender(sender, Channel.globalChat, sender))", "buttondevteam.lib.player.ChromaGamerBase.Companion.getFromSender", "buttondevteam.lib.chat.Command2MCSender", "buttondevteam.core.component.channel.Channel"))
fun getFromSender(sender: CommandSender): ChromaGamerBase { fun getFromSender(sender: CommandSender): ChromaGamerBase {
return getFromSender(Command2MCSender(sender, Channel.globalChat, sender))
}
/**
* Get from the given sender. the object's type will depend on the sender's type.
* Throws an exception if the sender type is not supported.
*
* @param sender The sender to use
* @return A user as returned by a converter
*/
@JvmStatic
fun getFromSender(sender: Command2Sender): ChromaGamerBase {
for (converter in senderConverters) { for (converter in senderConverters) {
val ocg = converter.apply(sender) val ocg = converter.apply(sender)
if (ocg.isPresent) return ocg.get() if (ocg.isPresent) return ocg.get()

View file

@ -2,12 +2,20 @@ package buttondevteam.lib.player
import buttondevteam.lib.architecture.IHaveConfig import buttondevteam.lib.architecture.IHaveConfig
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.entity.Player
import java.util.* import java.util.*
@AbstractUserClass(foldername = "minecraft", prototype = TBMCPlayer::class) @AbstractUserClass(foldername = "minecraft", prototype = TBMCPlayer::class)
@TBMCPlayerEnforcer @TBMCPlayerEnforcer
abstract class TBMCPlayerBase : ChromaGamerBase() { abstract class TBMCPlayerBase : ChromaGamerBase() {
val uniqueId: UUID by lazy { UUID.fromString(fileName) } val uniqueId: UUID by lazy { UUID.fromString(fileName) }
val player by lazy { Bukkit.getPlayer(uniqueId) }
val offlinePlayer by lazy { Bukkit.getOfflinePlayer(uniqueId) }
/**
* If the player is the console
*/
val isConsole = uniqueId == UUID(0, 0)
@JvmField @JvmField
val playerName = super.config.getData("PlayerName", "") val playerName = super.config.getData("PlayerName", "")
@ -36,6 +44,19 @@ abstract class TBMCPlayerBase : ChromaGamerBase() {
super.save() super.save()
} }
override fun sendMessage(message: String) {
// TODO: Random senders (Discord) won't receive messages. Including when trying to chat.
player?.sendMessage(message)
}
override fun sendMessage(message: Array<out String>) {
player?.sendMessage(*message)
}
override fun getName(): String {
return playerName.get()
}
companion object { companion object {
/** /**
* Get player as a plugin player. * Get player as a plugin player.
@ -63,5 +84,17 @@ abstract class TBMCPlayerBase : ChromaGamerBase() {
val p = Bukkit.getOfflinePlayer(name) val p = Bukkit.getOfflinePlayer(name)
return getPlayer(p.uniqueId, cl) return getPlayer(p.uniqueId, cl)
} }
fun <T : TBMCPlayerBase> getConsole(cl: Class<T>): T {
return getPlayer(UUID(0, 0), cl)
}
fun getConsole(): TBMCPlayerBase {
return getConsole(TBMCPlayerBase::class.java)
}
fun Player.asTBMC(): TBMCPlayerBase {
return getPlayer(uniqueId, TBMCPlayerBase::class.java)
}
} }
} }