Update config options and fix other issues and update Scala

This commit is contained in:
Norbi Peti 2023-06-29 02:10:20 +02:00
parent 6bd1de6217
commit 02e05e360e
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
16 changed files with 107 additions and 76 deletions

View file

@ -8,7 +8,7 @@ name := "Chroma-Discord"
version := "1.1"
scalaVersion := "3.2.2"
scalaVersion := "3.3.0"
resolvers += "spigot-repo" at "https://hub.spigotmc.org/nexus/content/repositories/snapshots/"
resolvers += "jitpack.io" at "https://jitpack.io"

View file

@ -1,6 +1,7 @@
package buttondevteam.discordplugin
import buttondevteam.lib.TBMCCoreAPI
import buttondevteam.lib.architecture.config.IConfigData
import buttondevteam.lib.architecture.{Component, ConfigData, IHaveConfig}
import discord4j.common.util.Snowflake
import discord4j.core.`object`.entity.channel.{Channel, MessageChannel}
@ -68,17 +69,17 @@ object DPUtils {
else DiscordPlugin.plugin.getLogger
}
def channelData(config: IHaveConfig, key: String): ConfigData[Mono[MessageChannel]] =
def channelData(config: IHaveConfig, key: String): IConfigData[Mono[MessageChannel]] =
config.getData(key, id => getMessageChannel(key, Snowflake.of(id.asInstanceOf[Long])),
(_: Mono[MessageChannel]) => 0L, 0L, true) //We can afford to search for the channel in the cache once (instead of using mainServer)
def roleData(config: IHaveConfig, key: String, defName: String): ConfigData[Mono[Role]] =
def roleData(config: IHaveConfig, key: String, defName: String): IConfigData[Mono[Role]] =
roleData(config, key, defName, Mono.just(DiscordPlugin.mainServer))
/**
* Needs to be a [[ConfigData]] for checking if it's set
*/
def roleData(config: IHaveConfig, key: String, defName: String, guild: Mono[Guild]): ConfigData[Mono[Role]] = config.getData(key, name => {
def roleData(config: IHaveConfig, key: String, defName: String, guild: Mono[Guild]): IConfigData[Mono[Role]] = config.getData(key, name => {
if (!name.isInstanceOf[String] || name.asInstanceOf[String].isEmpty) Mono.empty[Role]
else guild.flatMapMany(_.getRoles).filter(_.getName == name).onErrorResume(e => {
getLogger.warning("Failed to get role data for " + key + "=" + name + " - " + e.getMessage)
@ -86,7 +87,7 @@ object DPUtils {
}).next
}, _ => defName, defName, true)
def snowflakeData(config: IHaveConfig, key: String, defID: Long): ConfigData[Snowflake] =
def snowflakeData(config: IHaveConfig, key: String, defID: Long): IConfigData[Snowflake] =
config.getData(key, id => Snowflake.of(id.asInstanceOf[Long]), _.asLong, defID, true)
/**
@ -106,7 +107,7 @@ object DPUtils {
* @param configs The configs to check for null
* @return Whether the component got disabled and a warning logged
*/
def disableIfConfigError(@Nullable component: Component[DiscordPlugin], configs: ConfigData[_]*): Boolean = {
def disableIfConfigError(@Nullable component: Component[DiscordPlugin], configs: IConfigData[_]*): Boolean = {
for (config <- configs) {
val v = config.get
if (disableIfConfigErrorRes(component, config, v)) return true
@ -122,7 +123,7 @@ object DPUtils {
* @param result The result of getting the value
* @return Whether the component got disabled and a warning logged
*/
def disableIfConfigErrorRes(@Nullable component: Component[DiscordPlugin], config: ConfigData[_], result: Any): Boolean = {
def disableIfConfigErrorRes(@Nullable component: Component[DiscordPlugin], config: IConfigData[_], result: Any): Boolean = {
//noinspection ConstantConditions
if (result == null || (result.isInstanceOf[Mono[_]] && !result.asInstanceOf[Mono[_]].hasElement.block())) {
var path: String = null
@ -185,7 +186,7 @@ object DPUtils {
}).filter(ch => ch.isInstanceOf[MessageChannel]).cast(classOf[MessageChannel])
}
def getMessageChannel(config: ConfigData[Snowflake]): Mono[MessageChannel] =
def getMessageChannel(config: IConfigData[Snowflake]): Mono[MessageChannel] =
getMessageChannel(config.getPath, config.get)
def ignoreError[T](mono: Mono[T]): Mono[T] = mono.onErrorResume((_: Throwable) => Mono.empty)

View file

@ -14,6 +14,7 @@ import buttondevteam.discordplugin.role.GameRoleModule
import buttondevteam.discordplugin.util.{DPState, Timings}
import buttondevteam.lib.TBMCCoreAPI
import buttondevteam.lib.architecture.*
import buttondevteam.lib.architecture.config.IConfigData
import buttondevteam.lib.player.ChromaGamerBase
import com.google.common.io.Files
import discord4j.common.util.Snowflake
@ -77,16 +78,16 @@ import scala.jdk.OptionConverters.*
/**
* The (bot) channel to use for Discord commands like /role.
*/
def commandChannel: ConfigData[Snowflake] = DPUtils.snowflakeData(getIConfig, "commandChannel", 0L)
def commandChannel: IConfigData[Snowflake] = DPUtils.snowflakeData(getIConfig, "commandChannel", 0L)
/**
* The role that allows using mod-only Discord commands.
* If empty (&#39;&#39;), then it will only allow for the owner.
*/
def modRole: ConfigData[Mono[Role]] = DPUtils.roleData(getIConfig, "modRole", "Moderator")
def modRole: IConfigData[Mono[Role]] = DPUtils.roleData(getIConfig, "modRole", "Moderator")
/**
* The invite link to show by /discord invite. If empty, it defaults to the first invite if the bot has access.
*/
def inviteLink: ConfigData[String] = getIConfig.getData("inviteLink", "")
def inviteLink: IConfigData[String] = getIConfig.getData("inviteLink", "")
override def onLoad(): Unit = { //Needed by ServerWatcher
val thread = Thread.currentThread

View file

@ -15,9 +15,10 @@ class Command2DC extends Command2[ICommand2DC, Command2DCSender]('/', false) {
}
def registerCommand(command: ICommand2DC, appId: Long, guildId: Option[Long] = None): Unit = {
super.registerCommandSuper(command) //Needs to be configurable for the helps
val mainNode = super.registerCommandSuper(command) //Needs to be configurable for the helps
// TODO: Go through all subcommands and register them
val greetCmdRequest = ApplicationCommandRequest.builder()
.name(command.getCommandPath) //TODO: Main path
.name(mainNode.getName)
.description("Connect your Minecraft account.") //TODO: Description
.addOption(ApplicationCommandOptionData.builder()
.name("name")

View file

@ -15,7 +15,7 @@ class Command2DCSender(val event: ChatInputInteractionEvent) extends Command2Sen
override def sendMessage(message: String): Unit = {
if (message.isEmpty) return ()
//Some(message) map DPUtils.sanitizeString map { (msg: String) => Character.toLowerCase(msg.charAt(0)) + msg.substring(1) } foreach event.reply - don't even need this
event.reply(message);
event.reply(message)
}
override def sendMessage(message: Array[String]): Unit = sendMessage(String.join("\n", message: _*))

View file

@ -3,6 +3,7 @@ package buttondevteam.discordplugin.fun
import buttondevteam.core.ComponentManager
import buttondevteam.discordplugin.{DPUtils, DiscordPlugin}
import buttondevteam.lib.TBMCCoreAPI
import buttondevteam.lib.architecture.config.IConfigData
import buttondevteam.lib.architecture.{Component, ConfigData}
import com.google.common.collect.Lists
import discord4j.core.`object`.entity.channel.{GuildChannel, MessageChannel}
@ -97,7 +98,7 @@ class FunModule extends Component[DiscordPlugin] with Listener {
/**
* Questions that the bot will choose a random answer to give to.
*/
final private def serverReady: ConfigData[Array[String]] =
final private def serverReady: IConfigData[Array[String]] =
getConfig.getData("serverReady", Array[String](
"when will the server be open", "when will the server be ready",
"when will the server be done", "when will the server be complete",
@ -106,7 +107,7 @@ class FunModule extends Component[DiscordPlugin] with Listener {
/**
* Answers for a recognized question. Selected randomly.
*/
final private def serverReadyAnswers: ConfigData[util.ArrayList[String]] =
final private def serverReadyAnswers: IConfigData[util.ArrayList[String]] =
getConfig.getData("serverReadyAnswers", Lists.newArrayList(FunModule.serverReadyStrings: _*))
private def createUsableServerReadyStrings(): Unit =

View file

@ -123,7 +123,7 @@ class ChannelconCommand(private val module: MinecraftChatModule) extends IComman
}
val dcp: DiscordConnectedPlayer = DiscordConnectedPlayer.create(message.getAuthor.get, channel, chp.getUniqueId, Bukkit.getOfflinePlayer(chp.getUniqueId).getName, module)
//Using a fake player with no login/logout, should be fine for this event
val groupid: String = chan.get.getGroupID(dcp)
val groupid: String = chan.get.getGroupID(chp)
if (groupid == null && !((chan.get.isInstanceOf[ChatRoom]))) { //ChatRooms don't allow it unless the user joins, which happens later
DPUtils.reply(message, channel, "sorry, you cannot use that Minecraft channel.").subscribe()
return true

View file

@ -15,6 +15,7 @@ import discord4j.core.`object`.entity.channel.PrivateChannel
))
class MCChatCommand(private val module: MinecraftChatModule) extends ICommand2DC {
@Command2.Subcommand override def `def`(sender: Command2DCSender): Boolean = {
// TODO: If the user is logged in, don't let the object be removed from the cache (test first)
if (!module.allowPrivateChat.get) {
sender.sendMessage("Using the private chat is not allowed on this Minecraft server.")
return true

View file

@ -21,8 +21,8 @@ object MCChatCustom {
var gid: String = null
mcchannel match {
case room: ChatRoom =>
room.joinRoom(dcp)
gid = if (groupid == null) mcchannel.getGroupID(dcp) else groupid
room.joinRoom(dcp.getChromaUser)
gid = if (groupid == null) mcchannel.getGroupID(dcp.getChromaUser) else groupid
case _ =>
gid = groupid
}
@ -46,7 +46,7 @@ object MCChatCustom {
if (lmd.channel.getId.asLong != channel.asLong) true
else {
lmd.mcchannel match {
case room: ChatRoom => room.leaveRoom(lmd.dcp)
case room: ChatRoom => room.leaveRoom(lmd.dcp.getChromaUser)
case _ =>
}
false
@ -58,6 +58,7 @@ object MCChatCustom {
def getCustomChats: List[CustomLMD] = lastmsgCustom.toList
// TODO: Store Chroma user only
class CustomLMD private[mcchat](channel: MessageChannel, user: User, val groupID: String,
mcchannel: Channel, val dcp: DiscordConnectedPlayer, var toggles: Int,
var brtoggles: Set[TBMCSystemChatEvent.BroadcastTarget]) extends MCChatUtils.LastMsgData(channel, user, mcchannel) {

View file

@ -14,7 +14,9 @@ import discord4j.core.`object`.entity.{Member, Message, User}
import discord4j.core.event.domain.message.MessageCreateEvent
import discord4j.core.spec.EmbedCreateSpec
import discord4j.core.spec.legacy.{LegacyEmbedCreateSpec, LegacyMessageEditSpec}
import discord4j.rest.http.client.ClientException
import discord4j.rest.util.Color
import io.netty.handler.codec.http.HttpResponseStatus
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.{EventHandler, Listener}
@ -88,22 +90,22 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
time = se.getValue
val authorPlayer: String = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel.displayName.get) + "] " + //
(if ("Minecraft" == e.getOrigin) "" else "[" + e.getOrigin.charAt(0) + "]") +
DPUtils.sanitizeStringNoEscape(ChromaUtils.getDisplayName(e.getSender))
DPUtils.sanitizeStringNoEscape(e.getUser.getName)
val color: chat.Color = e.getChannel.color.get
val embed = () => {
val ecs = EmbedCreateSpec.builder()
ecs.description(e.getMessage).color(Color.of(color.getRed, color.getGreen, color.getBlue))
val url: String = module.profileURL.get
e.getSender match {
case player: Player =>
DPUtils.embedWithHead(ecs, authorPlayer, e.getSender.getName,
e.getUser match {
case player: TBMCPlayer =>
DPUtils.embedWithHead(ecs, authorPlayer, e.getUser.getName,
if (url.nonEmpty) url + "?type=minecraft&id=" + player.getUniqueId else null)
case dsender: DiscordSenderBase =>
case dsender: DiscordPlayer =>
ecs.author(authorPlayer,
if (url.nonEmpty) url + "?type=discord&id=" + dsender.getUser.getId.asString else null,
dsender.getUser.getAvatarUrl)
if (url.nonEmpty) url + "?type=discord&id=" + dsender.getDiscordID else null,
dsender.getDiscordUser.getAvatarUrl)
case _ =>
DPUtils.embedWithHead(ecs, authorPlayer, e.getSender.getName, null)
DPUtils.embedWithHead(ecs, authorPlayer, e.getUser.getName, null)
}
ecs.timestamp(time)
}
@ -120,13 +122,25 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
lastmsgdata.content = e.getMessage
}
else {
//TODO: The editing shouldn't be blocking, this whole method should be reactive
lastmsgdata.content = lastmsgdata.content + "\n" + e.getMessage // The message object doesn't get updated
lastmsgdata.message.edit().withEmbeds(embed().description(lastmsgdata.content).build()).block
try {
lastmsgdata.message.edit().withEmbeds(embed().description(lastmsgdata.content).build()).block
} catch {
case e: ClientException => {
// The message was deleted
if (e.getStatus ne HttpResponseStatus.NOT_FOUND) {
throw e
}
}
}
}
}
// Checks if the given channel is different than where the message was sent from
// Or if it was from MC
val isdifferentchannel: Predicate[Snowflake] = (id: Snowflake) => !((e.getSender.isInstanceOf[DiscordSenderBase])) || (e.getSender.asInstanceOf[DiscordSenderBase]).getChannel.getId.asLong != id.asLong
val isdifferentchannel: Predicate[Snowflake] = {
id => !e.getUser.isInstanceOf[DiscordPlayer] || e.getUser.asInstanceOf[DiscordSender].getChannel.getId.asLong != id.asLong
}
if (e.getChannel.isGlobal && (e.isFromCommand || isdifferentchannel.test(module.chatChannel.get))) {
if (MCChatUtils.lastmsgdata == null)
MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block(), null)
@ -143,7 +157,7 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
if ((e.isFromCommand || isdifferentchannel.test(lmd.channel.getId)) //Test if msg is from Discord
&& e.getChannel.getIdentifier == lmd.mcchannel.getIdentifier //If it's from a command, the command msg has been deleted, so we need to send it
&& e.getGroupID() == lmd.groupID) { //Check if this is the group we want to test - #58
if (e.shouldSendTo(lmd.dcp)) { //Check original user's permissions
if (e.shouldSendTo(lmd.dcp.getChromaUser)) { //Check original user's permissions
doit(lmd)
true
}
@ -370,8 +384,8 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
}
if (event.getMessage.getType eq Message.Type.CHANNEL_PINNED_MESSAGE) {
val mcchannel = if (clmd != null) clmd.mcchannel else dsender.getChromaUser.channel.get
val rtr = mcchannel getRTR (if (clmd != null) clmd.dcp else dsender)
val mcchannel = if (clmd != null) clmd.mcchannel else dsender.getChromaUser.getChannel.get
val rtr = mcchannel getRTR (if (clmd != null) clmd.dcp.getChromaUser else user)
TBMCChatAPI.SendSystemMessage(mcchannel, rtr, (dsender match {
case player: Player => player.getDisplayName
case _ => dsender.getName
@ -379,9 +393,9 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
false
}
else {
val cmb = ChatMessage.builder(dsender, user, dmessage + getAttachmentText).fromCommand(false)
val cmb = ChatMessage.builder(user, dmessage + getAttachmentText).fromCommand(false)
if (clmd != null)
TBMCChatAPI.sendChatMessage(cmb.permCheck(clmd.dcp).build, clmd.mcchannel)
TBMCChatAPI.sendChatMessage(cmb.permCheck(clmd.dcp.getChromaUser).build, clmd.mcchannel)
else
TBMCChatAPI.sendChatMessage(cmb.build)
true
@ -422,8 +436,8 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
if (dsender.isInstanceOf[DiscordSender] && runCustomCommand(dsender, cmdlowercased)) {
return ()
}
val channel = if (clmd == null) user.channel.get else clmd.mcchannel
val ev = new TBMCCommandPreprocessEvent(dsender, channel, dmessage, if (clmd == null) dsender else clmd.dcp)
val channel = if (clmd == null) user.getChannel.get else clmd.mcchannel
val ev = new TBMCCommandPreprocessEvent(user, channel, dmessage, if (clmd == null) user else clmd.dcp.getChromaUser)
Bukkit.getScheduler.runTask(DiscordPlugin.plugin, () => { //Commands need to be run sync
Bukkit.getPluginManager.callEvent(ev)
if (!ev.isCancelled)

View file

@ -27,14 +27,14 @@ object MCChatPrivate {
val mcm = ComponentManager.getIfEnabled(classOf[MinecraftChatModule])
if (start) {
val sender = DiscordConnectedPlayer.create(user, channel, mcp.getUniqueId, op.getName, mcm)
MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender)
MCChatUtils.addSenderTo(MCChatUtils.ConnectedSenders, user, sender)
MCChatUtils.LoggedInPlayers.put(mcp.getUniqueId, sender)
if (p == null) { // Player is offline - If the player is online, that takes precedence
MCChatUtils.callLoginEvents(sender)
}
}
else {
val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel.getId, user)
val sender = MCChatUtils.removeSenderFrom(MCChatUtils.ConnectedSenders, channel.getId, user)
assert(sender != null)
Bukkit.getScheduler.runTask(DiscordPlugin.plugin, () => {
def foo(): Unit = {
@ -69,7 +69,7 @@ object MCChatPrivate {
MCChatUtils.ConnectedSenders synchronized {
for ((_, userMap) <- MCChatUtils.ConnectedSenders) {
for (valueEntry <- asScala(userMap.entrySet)) {
if (MCChatUtils.getSender(MCChatUtils.OnlineSenders, valueEntry.getKey, valueEntry.getValue.getUser) == null) { //If the player is online then the fake player was already logged out
if (MCChatUtils.getSenderFrom(MCChatUtils.OnlineSenders, valueEntry.getKey, valueEntry.getValue.getUser) == null) { //If the player is online then the fake player was already logged out
MCChatUtils.callLogoutEvent(valueEntry.getValue, !Bukkit.isPrimaryThread)
}
}

View file

@ -7,6 +7,7 @@ import buttondevteam.discordplugin.DPUtils.SpecExtensions
import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule
import buttondevteam.discordplugin.mcchat.MCChatCustom.CustomLMD
import buttondevteam.discordplugin.mcchat.sender.{DiscordConnectedPlayer, DiscordPlayerSender, DiscordSender, DiscordSenderBase}
import buttondevteam.lib.player.{ChromaGamerBase, TBMCPlayerBase}
import buttondevteam.lib.{TBMCCoreAPI, TBMCSystemChatEvent}
import com.google.common.collect.Sets
import discord4j.common.util.Snowflake
@ -35,7 +36,7 @@ import scala.collection.convert.ImplicitConversions.`map AsJavaMap`
import scala.collection.mutable.ListBuffer
import scala.jdk.CollectionConverters.{CollectionHasAsScala, SeqHasAsJava}
import scala.jdk.javaapi.CollectionConverters.asScala
import scala.jdk.javaapi.OptionConverters._
import scala.jdk.javaapi.OptionConverters.*
object MCChatUtils {
/**
@ -87,7 +88,7 @@ object MCChatUtils {
gid == buttondevteam.core.component.channel.Channel.GROUP_EVERYONE //If null, allow if public (custom chats will have their channel stored anyway)
}
else {
gid == lmd.mcchannel.getGroupID(p)
gid == lmd.mcchannel.getGroupID(ChromaGamerBase.getFromSender(p))
}
).filter(MCChatUtils.checkEssentials) //If they can see it
.filter(_ => C.incrementAndGet > 0) //Always true
@ -102,10 +103,10 @@ object MCChatUtils {
!ess.getUser(p).isHidden
}
def addSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], user: User, sender: T): T =
addSender(senders, user.getId.asString, sender)
def addSenderTo[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], user: User, sender: T): T =
addSenderTo(senders, user.getId.asString, sender)
def addSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], did: String, sender: T): T = {
def addSenderTo[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], did: String, sender: T): T = {
val mapOpt = senders.get(did)
val map = if (mapOpt.isEmpty) new ConcurrentHashMap[Snowflake, T] else mapOpt.get
map.put(sender.getChannel.getId, sender)
@ -113,13 +114,13 @@ object MCChatUtils {
sender
}
def getSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
def getSenderFrom[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
val mapOpt = senders.get(user.getId.asString)
if (mapOpt.nonEmpty) mapOpt.get.get(channel)
else null.asInstanceOf
}
def removeSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
def removeSenderFrom[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
val mapOpt = senders.get(user.getId.asString)
if (mapOpt.nonEmpty) mapOpt.get.remove(channel)
else null.asInstanceOf
@ -153,15 +154,15 @@ object MCChatUtils {
* Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled.
*
* @param action The action to do
* @param sender The sender to check perms of or null to send to all that has it toggled
* @param permUser The user to check perms of or null to send to all that has it toggled
* @param toggle The toggle to check or null to send to all allowed
*/
def forAllowedCustomMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast): Mono[_] = {
def forAllowedCustomMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable permUser: ChromaGamerBase, @Nullable toggle: ChannelconBroadcast): Mono[_] = {
if (notEnabled) return Mono.empty
val st = MCChatCustom.lastmsgCustom.filter(clmd => { //new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple
if (toggle != null && ((clmd.toggles & (1 << toggle.id)) == 0)) false //If null then allow
else if (sender == null) true
else clmd.groupID.equals(clmd.mcchannel.getGroupID(sender))
else if (permUser == null) true
else clmd.groupID.equals(clmd.mcchannel.getGroupID(permUser))
}).map(cc => action.apply(Mono.just(cc.channel))) //TODO: Send error messages on channel connect
//Mono.whenDelayError((() => st.iterator).asInstanceOf[java.lang.Iterable[Mono[_]]]) //Can't convert as an iterator or inside the stream, but I can convert it as a stream
Mono.whenDelayError(st.asJava)
@ -171,13 +172,13 @@ object MCChatUtils {
* Do the {@code action} for each custom chat the {@code sender} have access to and has that broadcast type enabled.
*
* @param action The action to do
* @param sender The sender to check perms of or null to send to all that has it toggled
* @param permUser The user to check perms of or null to send to all that has it toggled
* @param toggle The toggle to check or null to send to all allowed
* @param hookmsg Whether the message is also sent from the hook
*/
def forAllowedCustomAndAllMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): Mono[_] = {
def forAllowedCustomAndAllMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable permUser: ChromaGamerBase, @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): Mono[_] = {
if (notEnabled) return Mono.empty
val cc = forAllowedCustomMCChat(action, sender, toggle)
val cc = forAllowedCustomMCChat(action, permUser, toggle)
if (!GeneralEventBroadcasterModule.isHooked || !hookmsg) return Mono.whenDelayError(forPublicPrivateChat(action), cc)
Mono.whenDelayError(cc)
}
@ -195,7 +196,7 @@ object MCChatUtils {
if (event.shouldSendTo(getSender(data.channel.getId, data.user)))
list.append(action(Mono.just(data.channel))) //TODO: Only store ID?
MCChatCustom.lastmsgCustom.filter(clmd =>
clmd.brtoggles.contains(event.getTarget) && event.shouldSendTo(clmd.dcp))
clmd.brtoggles.contains(event.getTarget) && event.shouldSendTo(clmd.dcp.getChromaUser))
.map(clmd => action(Mono.just(clmd.channel))).foreach(elem => {
list.append(elem)
()
@ -207,10 +208,10 @@ object MCChatUtils {
* This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc.
*/
private[mcchat] def getSender(channel: Snowflake, author: User): DiscordSenderBase = { //noinspection OptionalGetWithoutIsPresent
Option(getSender(OnlineSenders, channel, author)) // Find first non-null
.orElse(Option(getSender(ConnectedSenders, channel, author))) // This doesn't support the public chat, but it'll always return null for it
.orElse(Option(getSender(UnconnectedSenders, channel, author))) //
.orElse(Option(addSender(UnconnectedSenders, author,
Option(getSenderFrom(OnlineSenders, channel, author)) // Find first non-null
.orElse(Option(getSenderFrom(ConnectedSenders, channel, author))) // This doesn't support the public chat, but it'll always return null for it
.orElse(Option(getSenderFrom(UnconnectedSenders, channel, author))) //
.orElse(Option(addSenderTo(UnconnectedSenders, author,
new DiscordSender(author, DiscordPlugin.dc.getChannelById(channel).block().asInstanceOf[MessageChannel]))))
.get
}

View file

@ -3,7 +3,7 @@ package buttondevteam.discordplugin.mcchat
import buttondevteam.discordplugin.*
import buttondevteam.discordplugin.mcchat.sender.{DiscordConnectedPlayer, DiscordPlayer, DiscordPlayerSender}
import buttondevteam.lib.TBMCSystemChatEvent
import buttondevteam.lib.player.{TBMCPlayer, TBMCPlayerBase, TBMCYEEHAWEvent}
import buttondevteam.lib.player.{ChromaGamerBase, TBMCPlayer, TBMCPlayerBase, TBMCYEEHAWEvent}
import discord4j.common.util.Snowflake
import discord4j.core.`object`.entity.Role
import discord4j.core.`object`.entity.channel.MessageChannel
@ -36,8 +36,8 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
if (dp != null)
DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID)).flatMap(user =>
user.getPrivateChannel.flatMap(chan => module.chatChannelMono.flatMap(cc => {
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID, DiscordPlayerSender.create(user, chan, p, module))
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID, DiscordPlayerSender.create(user, cc, p, module)) //Stored per-channel
MCChatUtils.addSenderTo(MCChatUtils.OnlineSenders, dp.getDiscordID, DiscordPlayerSender.create(user, chan, p, module))
MCChatUtils.addSenderTo(MCChatUtils.OnlineSenders, dp.getDiscordID, DiscordPlayerSender.create(user, cc, p, module)) //Stored per-channel
Mono.empty
}))).subscribe()
val message = e.getJoinMessage
@ -51,7 +51,7 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
private def sendJoinLeaveMessage(message: String, player: Player): Unit =
if (message != null && message.trim.nonEmpty)
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), player, ChannelconBroadcast.JOINLEAVE, hookmsg = true).subscribe()
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), ChromaGamerBase.getFromSender(player), ChannelconBroadcast.JOINLEAVE, hookmsg = true).subscribe()
@EventHandler(priority = EventPriority.MONITOR) def onPlayerLeave(e: PlayerQuitEvent): Unit = {
if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return () // Only care about real users
@ -69,14 +69,14 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
}
@EventHandler(priority = EventPriority.LOW) def onPlayerDeath(e: PlayerDeathEvent): Unit =
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(e.getDeathMessage), e.getEntity, ChannelconBroadcast.DEATH, hookmsg = true).subscribe()
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(e.getDeathMessage), ChromaGamerBase.getFromSender(e.getEntity), ChannelconBroadcast.DEATH, hookmsg = true).subscribe()
@EventHandler def onPlayerAFK(e: AfkStatusChangeEvent): Unit = {
val base = e.getAffected.getBase
if (e.isCancelled || !base.isOnline) return ()
val msg = base.getDisplayName + " is " + (if (e.getValue) "now"
else "no longer") + " AFK."
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, hookmsg = false).subscribe()
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), ChromaGamerBase.getFromSender(base), ChannelconBroadcast.AFK, hookmsg = false).subscribe()
}
@EventHandler def onPlayerMute(e: MuteStatusChangeEvent): Unit = {

View file

@ -4,6 +4,7 @@ import buttondevteam.core.component.channel.Channel
import buttondevteam.discordplugin.mcchat.sender.DiscordConnectedPlayer
import buttondevteam.discordplugin.util.DPState
import buttondevteam.discordplugin.{ChannelconBroadcast, DPUtils, DiscordPlugin}
import buttondevteam.lib.architecture.config.IConfigData
import buttondevteam.lib.architecture.{Component, ConfigData}
import buttondevteam.lib.{TBMCCoreAPI, TBMCSystemChatEvent}
import com.google.common.collect.Lists
@ -37,56 +38,56 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
/**
* A list of commands that can be used in public chats - Warning: Some plugins will treat players as OPs, always test before allowing a command!
*/
def whitelistedCommands: ConfigData[util.ArrayList[String]] = getConfig.getData("whitelistedCommands",
def whitelistedCommands: IConfigData[util.ArrayList[String]] = getConfig.getData("whitelistedCommands",
Lists.newArrayList("list", "u", "shrug", "tableflip", "unflip", "mwiki", "yeehaw", "lenny", "rp", "plugins"))
/**
* The channel to use as the public Minecraft chat - everything public gets broadcasted here
*/
def chatChannel: ConfigData[Snowflake] = DPUtils.snowflakeData(getConfig, "chatChannel", 0L)
def chatChannel: IConfigData[Snowflake] = DPUtils.snowflakeData(getConfig, "chatChannel", 0L)
def chatChannelMono: Mono[MessageChannel] = DPUtils.getMessageChannel(chatChannel.getPath, chatChannel.get)
/**
* The channel where the plugin can log when it mutes a player on Discord because of a Minecraft mute
*/
def modlogChannel: ConfigData[Mono[MessageChannel]] = DPUtils.channelData(getConfig, "modlogChannel")
def modlogChannel: IConfigData[Mono[MessageChannel]] = DPUtils.channelData(getConfig, "modlogChannel")
/**
* The plugins to exclude from fake player events used for the 'mcchat' command - some plugins may crash, add them here
*/
def excludedPlugins: ConfigData[Array[String]] = getConfig.getData("excludedPlugins", Array[String]("ProtocolLib", "LibsDisguises", "JourneyMapServer"))
def excludedPlugins: IConfigData[Array[String]] = getConfig.getData("excludedPlugins", Array[String]("ProtocolLib", "LibsDisguises", "JourneyMapServer"))
/**
* If this setting is on then players logged in through the 'mcchat' command will be able to teleport using plugin commands.
* They can then use commands like /tpahere to teleport others to that place.<br />
* If this is off, then teleporting will have no effect.
*/
def allowFakePlayerTeleports: ConfigData[Boolean] = getConfig.getData("allowFakePlayerTeleports", false)
def allowFakePlayerTeleports: IConfigData[Boolean] = getConfig.getData("allowFakePlayerTeleports", false)
/**
* If this is on, each chat channel will have a player list in their description.
* It only gets added if there's no description yet or there are (at least) two lines of "----" following each other.
* Note that it will replace <b>everything</b> above the first and below the last "----" but it will only detect exactly four dashes.
* So if you want to use dashes for something else in the description, make sure it's either less or more dashes in one line.
*/
def showPlayerListOnDC: ConfigData[Boolean] = getConfig.getData("showPlayerListOnDC", true)
def showPlayerListOnDC: IConfigData[Boolean] = getConfig.getData("showPlayerListOnDC", true)
/**
* This setting controls whether custom chat connections can be <i>created</i> (existing connections will always work).
* Custom chat connections can be created using the channelcon command and they allow players to display town chat in a Discord channel for example.
* See the channelcon command for more details.
*/
def allowCustomChat: ConfigData[Boolean] = getConfig.getData("allowCustomChat", true)
def allowCustomChat: IConfigData[Boolean] = getConfig.getData("allowCustomChat", true)
/**
* This setting allows you to control if players can DM the bot to log on the server from Discord.
* This allows them to both chat and perform any command they can in-game.
*/
def allowPrivateChat: ConfigData[Boolean] = getConfig.getData("allowPrivateChat", true)
def allowPrivateChat: IConfigData[Boolean] = getConfig.getData("allowPrivateChat", true)
/**
* If set, message authors appearing on Discord will link to this URL. A 'type' and 'id' parameter will be added with the user's platform (Discord, Minecraft, ...) and ID.
*/
def profileURL: ConfigData[String] = getConfig.getData("profileURL", "")
def profileURL: IConfigData[String] = getConfig.getData("profileURL", "")
/**
* Enables support for running vanilla commands through Discord, if you ever need it.
*/
def enableVanillaCommands: ConfigData[Boolean] = getConfig.getData("enableVanillaCommands", true)
def enableVanillaCommands: IConfigData[Boolean] = getConfig.getData("enableVanillaCommands", true)
/**
* Whether players logged on from Discord (mcchat command) should be recognised by other plugins. Some plugins might break if it's turned off.
* But it's really hacky.

View file

@ -1,10 +1,14 @@
package buttondevteam.discordplugin.mcchat.sender
import buttondevteam.discordplugin.DiscordPlugin
import buttondevteam.discordplugin.mcchat.MCChatPrivate
import buttondevteam.lib.player.{ChromaGamerBase, UserClass}
import discord4j.common.util.Snowflake
import discord4j.core.`object`.entity.User
@UserClass(foldername = "discord") class DiscordPlayer() extends ChromaGamerBase {
private var did: String = null
private var discordUser: User = null
// private @Getter @Setter boolean minecraftChatEnabled;
def getDiscordID: String = {
@ -12,6 +16,11 @@ import buttondevteam.lib.player.{ChromaGamerBase, UserClass}
did
}
def getDiscordUser: User = {
if (discordUser == null) discordUser = DiscordPlugin.dc.getUserById(Snowflake.of(getDiscordID)).block() // TODO: Don't do it blocking
discordUser
}
/**
* Returns true if player has the private Minecraft chat enabled. For setting the value, see
* [[MCChatPrivate.privateMCChat]]

View file

@ -17,7 +17,7 @@ import java.util.UUID
* @param user May be null.
* @param channel May not be null.
*/
abstract class DiscordSenderBase protected(var user: User, var channel: MessageChannel) extends CommandSender {
abstract class DiscordSenderBase protected(var user: User, var channel: MessageChannel) extends CommandSender { // TODO: Move most of this to DiscordUser
private var msgtosend = ""
private var sendtask: BukkitTask = null