diff --git a/build.sbt b/build.sbt index 37b2629..c6f02c5 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ name := "Chroma-Discord" version := "1.1" -scalaVersion := "3.1.0" +scalaVersion := "3.2.2" resolvers += "spigot-repo" at "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" resolvers += "jitpack.io" at "https://jitpack.io" @@ -18,19 +18,21 @@ resolvers += Resolver.mavenLocal // assembly / assemblyOption := (assembly / assemblyOption).value.copy(includeScala = false) libraryDependencies ++= Seq( - "org.spigotmc" % "spigot" % "1.19.4-R0.1-SNAPSHOT" % Provided, "io.papermc.paper" % "paper-api" % "1.19.4-R0.1-SNAPSHOT" % Provided, - "com.discord4j" % "discord4j-core" % "3.2.2", - "org.slf4j" % "slf4j-jdk14" % "1.7.36", + "com.discord4j" % "discord4j-core" % "3.2.3", "com.vdurmont" % "emoji-java" % "5.1.1", - "org.mockito" % "mockito-core" % "4.6.1", - // https://mvnrepository.com/artifact/org.immutables/value - "org.immutables" % "value" % "2.9.0" % "provided", + "org.mockito" % "mockito-core" % "5.2.0", "com.github.TBMCPlugins.ChromaCore" % "Chroma-Core" % "v2.0.0-SNAPSHOT" % Provided, "net.ess3" % "EssentialsX" % "2.17.1" % Provided, "net.luckperms" % "api" % "5.4" % Provided, + // https://mvnrepository.com/artifact/com.mojang/brigadier + "com.mojang" % "brigadier" % "1.0.500" % "provided", + // https://mvnrepository.com/artifact/net.kyori/examination-api + "net.kyori" % "examination-api" % "1.3.0" % "provided", + // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib + "org.jetbrains.kotlin" % "kotlin-stdlib" % "1.8.20" % "provided" ) assembly / assemblyJarName := "Chroma-Discord.jar" @@ -44,6 +46,7 @@ assembly / assemblyMergeStrategy := { case PathList("META-INF", "io.netty.versions.properties") => MergeStrategy.concat // https://stackoverflow.com/a/55557287/457612 case "module-info.class" => MergeStrategy.discard + case "META-INF/versions/9/module-info.class" => MergeStrategy.discard case x => (assembly / assemblyMergeStrategy).value(x) } diff --git a/project/plugins.sbt b/project/plugins.sbt index 72477a2..f55a62c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.1") diff --git a/src/main/scala/buttondevteam/discordplugin/BukkitLogWatcher.scala b/src/main/scala/buttondevteam/discordplugin/BukkitLogWatcher.scala deleted file mode 100644 index ecec820..0000000 --- a/src/main/scala/buttondevteam/discordplugin/BukkitLogWatcher.scala +++ /dev/null @@ -1,17 +0,0 @@ -package buttondevteam.discordplugin - -import buttondevteam.discordplugin.mcchat.MinecraftChatModule -import buttondevteam.discordplugin.util.DPState -import org.apache.logging.log4j.Level -import org.apache.logging.log4j.core.appender.AbstractAppender -import org.apache.logging.log4j.core.filter.LevelRangeFilter -import org.apache.logging.log4j.core.layout.PatternLayout -import org.apache.logging.log4j.core.{Filter, LogEvent} - -class BukkitLogWatcher private[discordplugin]() extends AbstractAppender("ChromaDiscord", - LevelRangeFilter.createFilter(Level.INFO, Level.INFO, Filter.Result.ACCEPT, Filter.Result.DENY), - PatternLayout.createDefaultLayout) { - override def append(logEvent: LogEvent): Unit = - if (logEvent.getMessage.getFormattedMessage.contains("Attempting to restart with ")) - MinecraftChatModule.state = DPState.RESTARTING_SERVER -} \ No newline at end of file diff --git a/src/main/scala/buttondevteam/discordplugin/DPUtils.scala b/src/main/scala/buttondevteam/discordplugin/DPUtils.scala index e0576c3..db4659b 100644 --- a/src/main/scala/buttondevteam/discordplugin/DPUtils.scala +++ b/src/main/scala/buttondevteam/discordplugin/DPUtils.scala @@ -1,7 +1,7 @@ package buttondevteam.discordplugin import buttondevteam.lib.TBMCCoreAPI -import buttondevteam.lib.architecture.{Component, ConfigData, IHaveConfig, ReadOnlyConfigData} +import buttondevteam.lib.architecture.{Component, ConfigData, IHaveConfig} import discord4j.common.util.Snowflake import discord4j.core.`object`.entity.channel.{Channel, MessageChannel} import discord4j.core.`object`.entity.{Guild, Message, Role} @@ -182,7 +182,7 @@ object DPUtils { DiscordPlugin.dc.getChannelById(id).onErrorResume(e => { getLogger.warning(s"Failed to get channel data for $key=$id - ${e.getMessage}") Mono.empty[Channel] - }).filter(ch => ch.isInstanceOf[MessageChannel]).cast(classOf[MessageChannel]]) + }).filter(ch => ch.isInstanceOf[MessageChannel]).cast(classOf[MessageChannel]) } def getMessageChannel(config: ConfigData[Snowflake]): Mono[MessageChannel] = diff --git a/src/main/scala/buttondevteam/discordplugin/DiscordPlugin.scala b/src/main/scala/buttondevteam/discordplugin/DiscordPlugin.scala index 54d0125..fc388c8 100644 --- a/src/main/scala/buttondevteam/discordplugin/DiscordPlugin.scala +++ b/src/main/scala/buttondevteam/discordplugin/DiscordPlugin.scala @@ -26,8 +26,6 @@ import discord4j.core.{DiscordClientBuilder, GatewayDiscordClient} import discord4j.gateway.ShardInfo import discord4j.rest.interaction.Interactions import discord4j.store.jdk.JdkStoreService -import org.apache.logging.log4j.LogManager -import org.apache.logging.log4j.core.Logger import org.bukkit.command.CommandSender import org.bukkit.configuration.file.YamlConfiguration import org.mockito.internal.util.MockUtil @@ -59,7 +57,6 @@ import scala.jdk.OptionConverters.* def manager: Command2DC = _manager private var starting = false - private var logWatcher: BukkitLogWatcher = null /** * The prefix to use with Discord commands like /role. It only works in the bot channel. */ @@ -206,10 +203,7 @@ import scala.jdk.OptionConverters.* manager.registerCommand(new ConnectCommand, applicationId, guildId) TBMCCoreAPI.SendUnsentExceptions() TBMCCoreAPI.SendUnsentDebugMessages() - val blw = new BukkitLogWatcher - blw.start() - LogManager.getRootLogger.asInstanceOf[Logger].addAppender(blw) - logWatcher = blw + // TODO: Removed log watcher (responsible for detecting restarts) if (!TBMCCoreAPI.IsTestServer) DiscordPlugin.dc.updatePresence(ClientPresence.online(ClientActivity.playing("Minecraft"))).subscribe() else DiscordPlugin.dc.updatePresence(ClientPresence.online(ClientActivity.playing("testing"))).subscribe() getLogger.info("Loaded!") @@ -244,7 +238,6 @@ import scala.jdk.OptionConverters.* try { DiscordPlugin.SafeMode = true // Stop interacting with Discord ChromaBot.enabled = false - LogManager.getRootLogger.asInstanceOf[Logger].removeAppender(logWatcher) timings.printElapsed("Logging out...") DiscordPlugin.dc.logout.block DiscordPlugin.mainServer = null //Allow ReadyEvent again diff --git a/src/main/scala/buttondevteam/discordplugin/commands/Command2DC.scala b/src/main/scala/buttondevteam/discordplugin/commands/Command2DC.scala index 78ccce0..acc3aeb 100644 --- a/src/main/scala/buttondevteam/discordplugin/commands/Command2DC.scala +++ b/src/main/scala/buttondevteam/discordplugin/commands/Command2DC.scala @@ -2,6 +2,7 @@ package buttondevteam.discordplugin.commands import buttondevteam.discordplugin.DiscordPlugin import buttondevteam.lib.chat.Command2 +import buttondevteam.lib.chat.commands.SubcommandData import discord4j.common.util.Snowflake import discord4j.core.`object`.command.ApplicationCommandOption import discord4j.discordjson.json.{ApplicationCommandOptionData, ApplicationCommandRequest} @@ -14,7 +15,7 @@ class Command2DC extends Command2[ICommand2DC, Command2DCSender]('/', false) { } def registerCommand(command: ICommand2DC, appId: Long, guildId: Option[Long] = None): Unit = { - super.registerCommand(command) //Needs to be configurable for the helps + super.registerCommandSuper(command) //Needs to be configurable for the helps val greetCmdRequest = ApplicationCommandRequest.builder() .name(command.getCommandPath) //TODO: Main path .description("Connect your Minecraft account.") //TODO: Description @@ -32,7 +33,7 @@ class Command2DC extends Command2[ICommand2DC, Command2DCSender]('/', false) { } } - override def hasPermission(sender: Command2DCSender, command: ICommand2DC, method: Method): Boolean = { + override def hasPermission(sender: Command2DCSender, data: SubcommandData[ICommand2DC, Command2DCSender]): Boolean = { //return !command.isModOnly() || sender.getMessage().getAuthor().hasRole(DiscordPlugin.plugin.modRole().get()); //TODO: modRole may be null; more customisable way? true } diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/ChannelconCommand.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/ChannelconCommand.scala index 3cfb921..e49d962 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/ChannelconCommand.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/ChannelconCommand.scala @@ -71,7 +71,7 @@ class ChannelconCommand(private val module: MinecraftChatModule) extends IComman DPUtils.reply(message, Mono.empty, "cannot find toggle. Toggles:\n" + togglesString.get).subscribe() return true } - val add: Boolean = !(cc.brtoggles.contains(bt)) + val add: Boolean = !cc.brtoggles.contains(bt) if (add) { cc.brtoggles += bt } @@ -106,8 +106,7 @@ class ChannelconCommand(private val module: MinecraftChatModule) extends IComman if (MCChatCustom.hasCustomChat(message.getChannelId)) { return respond(sender, "this channel is already connected to a Minecraft channel. Use `@ChromaBot channelcon remove` to remove it.") } - val chan: Optional[Channel] = Channel.getChannels.filter(ch => ch.getIdentifier.equalsIgnoreCase(channelID) - || util.Arrays.stream(ch.extraIdentifiers.get).anyMatch(cid => cid.equalsIgnoreCase(channelID))).findAny + val chan: Optional[Channel] = Channel.getChannels.filter(ch => ch.getIdentifier.equalsIgnoreCase(channelID)).findAny // TODO: Removed erroring shit if (!chan.isPresent) { //TODO: Red embed that disappears over time (kinda like the highlight messages in OW) DPUtils.reply(message, channel, "MC channel with ID '" + channelID + "' not found! The ID is the command for it without the /.").subscribe() return true diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/MCChatUtils.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/MCChatUtils.scala index c077da2..9ac98b1 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/MCChatUtils.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/MCChatUtils.scala @@ -228,14 +228,10 @@ object MCChatUtils { else lastmsgdata.message = null return () } // Don't set the whole object to null, the player and channel information should be preserved - for (data <- if (channel.isInstanceOf[PrivateChannel]) MCChatPrivate.lastmsgPerUser - else MCChatCustom.lastmsgCustom) { - if (data.channel.getId.asLong == channel.getId.asLong) { - data.message = null - return () - } - } - //If it gets here, it's sending a message to a non-chat channel + val channelData = if (channel.isInstanceOf[PrivateChannel]) MCChatPrivate.lastmsgPerUser else MCChatCustom.lastmsgCustom + channelData.collectFirst({ case data if data.channel.getId.asLong == channel.getId.asLong => data }) + .foreach(data => data.message = null) + //If the above didn't find anything, it's sending a message to a non-chat channel } def addStaticExcludedPlugin(event: Class[_ <: Event], plugin: String): util.HashSet[String] = diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/MCListener.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/MCListener.scala index 2a86078..bef2bb8 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/MCListener.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/MCListener.scala @@ -1,7 +1,6 @@ package buttondevteam.discordplugin.mcchat import buttondevteam.discordplugin.* -import buttondevteam.discordplugin.DPUtils.{FluxExtensions, MonoExtensions} import buttondevteam.discordplugin.mcchat.sender.{DiscordConnectedPlayer, DiscordPlayer, DiscordPlayerSender} import buttondevteam.lib.TBMCSystemChatEvent import buttondevteam.lib.player.{TBMCPlayer, TBMCPlayerBase, TBMCYEEHAWEvent} diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/MinecraftChatModule.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/MinecraftChatModule.scala index 8e88d65..bedd55a 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/MinecraftChatModule.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/MinecraftChatModule.scala @@ -1,11 +1,10 @@ package buttondevteam.discordplugin.mcchat import buttondevteam.core.component.channel.Channel -import buttondevteam.discordplugin.DPUtils.{MonoExtensions, SpecExtensions} import buttondevteam.discordplugin.mcchat.sender.DiscordConnectedPlayer import buttondevteam.discordplugin.util.DPState import buttondevteam.discordplugin.{ChannelconBroadcast, DPUtils, DiscordPlugin} -import buttondevteam.lib.architecture.{Component, ConfigData, ReadOnlyConfigData} +import buttondevteam.lib.architecture.{Component, ConfigData} import buttondevteam.lib.{TBMCCoreAPI, TBMCSystemChatEvent} import com.google.common.collect.Lists import discord4j.common.util.Snowflake diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordConnectedPlayer.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordConnectedPlayer.scala index 3f29872..f23e510 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordConnectedPlayer.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordConnectedPlayer.scala @@ -3,6 +3,7 @@ package buttondevteam.discordplugin.mcchat.sender import buttondevteam.discordplugin.mcchat.MinecraftChatModule import discord4j.core.`object`.entity.User import discord4j.core.`object`.entity.channel.MessageChannel +import net.kyori.adventure.text.Component import org.bukkit.* import org.bukkit.attribute.{Attribute, AttributeInstance, AttributeModifier} import org.bukkit.entity.{Entity, Player} @@ -49,12 +50,12 @@ object DiscordConnectedPlayer { * @param user May be null. * @param channel May not be null. * @param uniqueId The UUID of the player. - * @param name The Minecraft name of the player. + * @param playerName The Minecraft name of the player. * @param module The MinecraftChatModule or null if testing. */ -abstract class DiscordConnectedPlayer(user: User, channel: MessageChannel, val uniqueId: UUID, val name: String, val module: MinecraftChatModule) extends DiscordSenderBase(user, channel) with IMCPlayer[DiscordConnectedPlayer] { +abstract class DiscordConnectedPlayer(user: User, channel: MessageChannel, val uniqueId: UUID, val playerName: String, val module: MinecraftChatModule) extends DiscordSenderBase(user, channel) with IMCPlayer[DiscordConnectedPlayer] { private var loggedIn = false - private var displayName: String = name + private var displayName: String = playerName private var location: Location = if (module == null) null else Bukkit.getWorlds.get(0).getSpawnLocation private val basePlayer: OfflinePlayer = if (module == null) null else Bukkit.getOfflinePlayer(uniqueId) @@ -98,7 +99,7 @@ abstract class DiscordConnectedPlayer(user: User, channel: MessageChannel, val u def isLoggedIn: Boolean = this.loggedIn - override def getName: String = this.name + override def getName: String = this.playerName def getBasePlayer: OfflinePlayer = this.basePlayer @@ -196,6 +197,8 @@ abstract class DiscordConnectedPlayer(user: User, channel: MessageChannel, val u override def getInventory: PlayerInventory = inventory + override def name(): Component = Component.text(playerName) + //noinspection ScalaDeprecation /*@SuppressWarnings(Array("deprecation")) override def spigot: super.Spigot = new super.Spigot() { override def getRawAddress: InetSocketAddress = null diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordPlayerSender.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordPlayerSender.scala index f5132f3..edc1e27 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordPlayerSender.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordPlayerSender.scala @@ -32,7 +32,7 @@ abstract class DiscordPlayerSender(user: User, channel: MessageChannel, var play super.sendMessage(message) } - override def sendMessage(messages: Array[String]): Unit = { + override def sendMessage(messages: Array[? <: String]): Unit = { player.sendMessage(messages*) super.sendMessage(messages) } diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSender.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSender.scala index 866b845..f6d6c00 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSender.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSender.scala @@ -3,18 +3,19 @@ package buttondevteam.discordplugin.mcchat.sender import buttondevteam.discordplugin.DiscordPlugin import discord4j.core.`object`.entity.User import discord4j.core.`object`.entity.channel.MessageChannel +import net.kyori.adventure.text.{Component, ComponentBuilder, TextComponent} import org.bukkit.command.CommandSender import org.bukkit.permissions.{PermissibleBase, Permission, PermissionAttachment, PermissionAttachmentInfo} import org.bukkit.plugin.Plugin import org.bukkit.{Bukkit, Server} import reactor.core.publisher.Mono -import scala.jdk.OptionConverters._ +import scala.jdk.OptionConverters.* import java.util class DiscordSender(user: User, channel: MessageChannel, pname: String) extends DiscordSenderBase(user, channel) with CommandSender { private val perm = new PermissibleBase(this) - private val name: String = Option(pname) + private val senderName: String = Option(pname) .orElse(Option(user).flatMap(u => u.asMember(DiscordPlugin.mainServer.getId) .onErrorResume(_ => Mono.empty).blockOptional().toScala .map(u => u.getDisplayName))) @@ -56,7 +57,9 @@ class DiscordSender(user: User, channel: MessageChannel, pname: String) extends override def getServer: Server = Bukkit.getServer - override def getName: String = name + override def getName: String = senderName + + override def name(): Component = Component.text(senderName) //override def spigot(): CommandSender.Spigot = new CommandSender.Spigot override def spigot(): CommandSender.Spigot = ??? diff --git a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSenderBase.scala b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSenderBase.scala index 4fffdc7..1c371c3 100644 --- a/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSenderBase.scala +++ b/src/main/scala/buttondevteam/discordplugin/mcchat/sender/DiscordSenderBase.scala @@ -10,6 +10,8 @@ import org.bukkit.Bukkit import org.bukkit.command.CommandSender import org.bukkit.scheduler.BukkitTask +import java.util.UUID + /** * * @param user May be null. @@ -62,5 +64,8 @@ abstract class DiscordSenderBase protected(var user: User, var channel: MessageC TBMCCoreAPI.SendException("An error occured while sending message to DiscordSender", e, DiscordPlugin.plugin) } - override def sendMessage(messages: Array[String]): Unit = sendMessage(String.join("\n", messages: _*)) + override def sendMessage(messages: Array[? <: String]): Unit = sendMessage(String.join("\n", messages: _*)) + + override def sendMessage(sender: UUID, message: String): Unit = sendMessage(message) + override def sendMessage(sender: UUID, messages: Array[? <: String]): Unit = sendMessage(messages) } \ No newline at end of file