diff --git a/README.md b/README.md index f587381..a906287 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,11 @@ ![license](https://img.shields.io/github/license/quantiom/EventHandler?color=%23b59e28&style=for-the-badge) ![made-with-kotlin](https://img.shields.io/badge/MADE%20WITH-KOTLIN-%23b59e28?style=for-the-badge&logo=java) ![last-commit](https://img.shields.io/github/last-commit/quantiom/AdvancedVanish?color=%23b59e28&style=for-the-badge) AdvancedVanish is a fully customizable and advanced vanish plugin made with Kotlin. + Spigot Resource: https://www.spigotmc.org/resources/advancedvanish.86036/ +GitBook: https://quantioms.gitbook.io/advancedvanish/ + ## Features - Fully customizable through the [config](src/main/resources/config.yml). (70+ options) - Messages @@ -13,7 +16,7 @@ Spigot Resource: https://www.spigotmc.org/resources/advancedvanish.86036/ - Placeholders - Much more... - Vanished players are **completely** invisible, as if they are not even online. -- Vanish priorities/levels ([more info](https://github.com/quantiom/AdvancedVanish/blob/main/src/main/resources/config.yml#L93-L114)) +- Vanish priorities/levels ([more info](https://quantioms.gitbook.io/advancedvanish/features#vanish-priorities)) - Supports many different permissions plugins. (LuckPerms, PermissionsEx, bPermissions, GroupManager) - Many configurable hooks which provide support to other plugins. - Essentials @@ -30,14 +33,16 @@ Spigot Resource: https://www.spigotmc.org/resources/advancedvanish.86036/ - `/vanish status ` *- Check if a player is in vanish.* - `/vanish set ` *- Set another player's vanish.* - `/vanish toggle ` *- Toggle another player's vanish.* -- For the rest of the features, check out the [config](src/main/resources/config.yml). + - `/vanish interact` *- Toggles interacting while in vanish* +- Cross Server Vanish Synchronization +- For the rest of the features, check out the [GitBook page](https://quantioms.gitbook.io/advancedvanish/). ## Hooks In AdvancedVanish, there are many hooks which provide support to other plugins. -A full list of hooks with their descriptions can be found in the [config](src/main/resources/config.yml). +A full list of hooks with their descriptions can be found on the [GitBook page](https://quantioms.gitbook.io/advancedvanish/features#hooks). ## Vanish Priority -An explanation and guide of how to use vanish priorities can be found in the [config](src/main/resources/config.yml). +An explanation and guide of how to use vanish priorities can be found on the [GitBook page](https://quantioms.gitbook.io/advancedvanish/features#vanish-priorities). *Note: Requires a supported permissions plugin to function* ## API @@ -49,17 +54,18 @@ your plugin's `plugin.yml`. Add this repository to your `pom.xml`: ```xml - jitpack.io - https://jitpack.io - + repsy + quantiom + https://repo.repsy.io/mvn/quantiom/minecraft + ``` Add the dependency and replace `...` with the current version: ```xml - com.github.quantiom - AdvancedVanish - v1.1.8 + me.quantiom + advancedvanish + 1.2.4 ``` diff --git a/pom.xml b/pom.xml index 53f57b7..b99651c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,18 +5,27 @@ me.quantiom advancedvanish - 1.1.8 + 1.2.4 jar AdvancedVanish A fully customizable and advanced vanish plugin. + https://www.spigotmc.org/resources/advancedvanish.86036/ + + + + repsy + quantiom + https://repo.repsy.io/mvn/quantiom/minecraft + + UTF-8 - 1.6.0 + 1.7.10 official 4.13.1 - 8 + 10 @@ -34,7 +43,7 @@ ess-repo - https://ci.ender.zone/plugin/repository/everything/ + https://repo.essentialsx.net/releases/ paper-repo @@ -56,6 +65,14 @@ codemc-repo https://repo.codemc.org/repository/maven-public/ + + MikeRepo + https://repo.mikeprimm.com/ + + + AlessioDP + https://repo.alessiodp.com/releases/ + @@ -63,6 +80,7 @@ org.jetbrains.kotlin kotlin-stdlib ${kotlin.version} + provided org.spigotmc @@ -96,9 +114,9 @@ provided - net.ess3 + net.essentialsx EssentialsX - 2.17.2 + 2.19.7 provided @@ -138,9 +156,9 @@ provided - com.github.webbukkit + us.dynmap dynmap-api - 2.5 + 3.4-beta-3 provided @@ -161,6 +179,62 @@ 7.4 provided + + + + net.kyori + adventure-api + 4.11.0 + provided + + + net.kyori + adventure-platform-api + 4.1.2 + provided + + + net.kyori + adventure-platform-bukkit + 4.1.2 + provided + + + net.kyori + adventure-text-minimessage + 4.11.0 + provided + + + + redis.clients + jedis + 4.2.0 + provided + + + org.jetbrains.exposed + exposed-core + 0.39.2 + provided + + + org.jetbrains.exposed + exposed-dao + 0.39.2 + provided + + + org.jetbrains.exposed + exposed-jdbc + 0.39.2 + provided + + + net.byteflux + libby-bukkit + 1.1.5 + @@ -253,7 +327,7 @@ co.aikar.commands - me.quantiom.advancedvanish.acf + me.quantiom.advancedvanish.shaded.acf co.aikar.locales @@ -261,7 +335,19 @@ kotlin - me.quantiom.kotlin + me.quantiom.advancedvanish.shaded.kotlin + + + net.kyori.adventure + me.quantiom.advancedvanish.shaded.adventure + + + net.byteflux.libby + me.quantiom.advancedvanish.shaded.libby + + + org.jetbrains.exposed + me.quantiom.advancedvanish.shaded.exposed diff --git a/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanish.kt b/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanish.kt index a0e2999..1f0a56d 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanish.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanish.kt @@ -7,26 +7,30 @@ import me.quantiom.advancedvanish.hook.HooksManager import me.quantiom.advancedvanish.listener.VanishListener import me.quantiom.advancedvanish.permission.PermissionsManager import me.quantiom.advancedvanish.state.VanishStateManager +import me.quantiom.advancedvanish.sync.ServerSyncManager import me.quantiom.advancedvanish.util.AdvancedVanishAPI +import me.quantiom.advancedvanish.util.DependencyManager import me.quantiom.advancedvanish.util.UpdateChecker +import net.kyori.adventure.platform.bukkit.BukkitAudiences import org.bukkit.Bukkit import org.bukkit.plugin.java.JavaPlugin import java.util.logging.Level -class AdvancedVanish : JavaPlugin() { - companion object { - var instance: AdvancedVanish? = null - var commandManager: PaperCommandManager? = null +object AdvancedVanish { + var instance: AdvancedVanishPlugin? = null + var commandManager: PaperCommandManager? = null + var adventure: BukkitAudiences? = null - fun log(level: Level, msg: String) { - instance!!.logger.log(level, msg) - } + fun log(level: Level, msg: String) { + instance!!.logger.log(level, msg) } - override fun onEnable() { - instance = this + fun onEnable(plugin: AdvancedVanishPlugin) { + instance = plugin + + adventure = BukkitAudiences.create(plugin) - commandManager = PaperCommandManager(this).also { + commandManager = PaperCommandManager(plugin).also { it.enableUnstableAPI("help") it.registerCommand(VanishCommand, true) } @@ -36,20 +40,23 @@ class AdvancedVanish : JavaPlugin() { // update checker if (Config.getValueOrDefault("check-for-updates", true)) { UpdateChecker.getVersion { - if (it != this.description.version) { - this.logger.info("A new update for AdvancedVanish (v${it}) is available:") - this.logger.info("https://www.spigotmc.org/resources/advancedvanish.86036/") + if (it != plugin.description.version) { + plugin.logger.info("A new update for AdvancedVanish (v${it}) is available:") + plugin.logger.info("https://www.spigotmc.org/resources/advancedvanish.86036/") } } } - this.server.pluginManager.registerEvents(VanishListener, this) + plugin.server.pluginManager.registerEvents(ServerSyncManager, plugin) + plugin.server.pluginManager.registerEvents(VanishListener, plugin) PermissionsManager.setupPermissionsHandler() HooksManager.setupHooks() } - override fun onDisable() { + fun onDisable() { + adventure?.close() + ServerSyncManager.close() VanishStateManager.onDisable() AdvancedVanishAPI.vanishedPlayers.map(Bukkit::getPlayer).forEach { AdvancedVanishAPI.unVanishPlayer(it!!) } HooksManager.disableHooks() diff --git a/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanishPlugin.java b/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanishPlugin.java new file mode 100644 index 0000000..a1e0e62 --- /dev/null +++ b/src/main/kotlin/me/quantiom/advancedvanish/AdvancedVanishPlugin.java @@ -0,0 +1,28 @@ +package me.quantiom.advancedvanish; + +import me.quantiom.advancedvanish.util.DependencyManager; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * This class is written in Java only because of the + * dependency management system. After Kotlin is loaded, the + * AdvancedVanish Kotlin class will take over. + * + * Basically, this class just acts as a "loader". + */ + +public class AdvancedVanishPlugin extends JavaPlugin { + @Override + public void onEnable() { + // load dependencies + DependencyManager dependencyManager = new DependencyManager(this); + dependencyManager.loadDependencies(); + + AdvancedVanish.INSTANCE.onEnable(this); + } + + @Override + public void onDisable() { + AdvancedVanish.INSTANCE.onDisable(); + } +} diff --git a/src/main/kotlin/me/quantiom/advancedvanish/command/VanishCommand.kt b/src/main/kotlin/me/quantiom/advancedvanish/command/VanishCommand.kt index bdfcc4a..a49a1c2 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/command/VanishCommand.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/command/VanishCommand.kt @@ -8,10 +8,7 @@ import me.quantiom.advancedvanish.config.Config import me.quantiom.advancedvanish.hook.HooksManager import me.quantiom.advancedvanish.permission.PermissionsManager import me.quantiom.advancedvanish.state.VanishStateManager -import me.quantiom.advancedvanish.util.AdvancedVanishAPI -import me.quantiom.advancedvanish.util.color -import me.quantiom.advancedvanish.util.isVanished -import me.quantiom.advancedvanish.util.sendConfigMessage +import me.quantiom.advancedvanish.util.* import org.bukkit.Bukkit import org.bukkit.command.CommandSender import org.bukkit.entity.Player @@ -20,17 +17,17 @@ import org.bukkit.entity.Player object VanishCommand : BaseCommand() { private val HELP_MESSAGE = listOf( "", - "&c&m----------&c&l AdvancedVanish &c&m----------", - "&c/vanish &8- &fToggle vanish.", - "&c/vanish version &8- &fShows the version of the plugin.", - "&c/vanish reload &8- &fReloads the config and hooks.", - "&c/vanish interact &8- &fToggles interacting with blocks while in vanish.", - "&c/vanish priority &8- &fDisplays your vanish priority.", - "&c/vanish list &8- &fDisplays a list of vanished players.", - "&c/vanish status &8- &fCheck if a player is in vanish.", - "&c/vanish set &8- &fSet another player's vanish.", - "&c/vanish toggle &8- &fToggle another player's vanish.", - "&c&m-----------------------------------", + "---------- AdvancedVanish ----------", + "/vanish - Toggle vanish.", + "/vanish version - Shows the version of the plugin.", + "/vanish reload - Reloads the config and hooks.", + "/vanish interact - Toggles interacting with blocks while in vanish.", + "/vanish priority - Displays your vanish priority.", + "/vanish list - Displays a list of vanished players.", + "/vanish status - Check if a player is in vanish.", + "/vanish set - Set another player's vanish.", + "/vanish toggle - Toggle another player's vanish.", + "-----------------------------------", "" ) @@ -125,8 +122,6 @@ object VanishCommand : BaseCommand() { val toChange = status.lowercase() == "on" || status.lowercase() == "true" var sendAlready = false - println(toChange) - if (target.player.isVanished()) { if (toChange) { sendAlready = true @@ -179,7 +174,7 @@ object VanishCommand : BaseCommand() { private fun onHelp(sender: CommandSender) { if (!permissionCheck(sender, "permissions.help-command", "advancedvanish.help-command")) return - this.HELP_MESSAGE.forEach { sender.sendMessage(it.color()) } + this.HELP_MESSAGE.forEach { sender.sendComponentMessage(it.color()) } } private fun permissionCheck(sender: CommandSender, key: String, default: String): Boolean { diff --git a/src/main/kotlin/me/quantiom/advancedvanish/config/Config.kt b/src/main/kotlin/me/quantiom/advancedvanish/config/Config.kt index 2fb27a4..48b410d 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/config/Config.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/config/Config.kt @@ -6,9 +6,15 @@ import co.aikar.locales.MessageKeyProvider import com.google.common.collect.Maps import com.google.common.io.Closeables import me.quantiom.advancedvanish.AdvancedVanish +import me.quantiom.advancedvanish.sync.ServerSyncManager import me.quantiom.advancedvanish.state.VanishStateManager import me.quantiom.advancedvanish.util.applyPlaceholders import me.quantiom.advancedvanish.util.color +import me.quantiom.advancedvanish.util.colorLegacy +import me.quantiom.advancedvanish.util.sendComponentMessage +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import org.bukkit.command.CommandSender import org.bukkit.configuration.file.FileConfiguration import org.bukkit.configuration.file.YamlConfiguration @@ -56,7 +62,8 @@ object Config { } // config-version check - if (this.getValueOrDefault("config-version", CONFIG_VERSION) != CONFIG_VERSION) { + val currentConfigVersion = this.getValueOrDefault("config-version", CONFIG_VERSION)!! + if (currentConfigVersion != CONFIG_VERSION) { File(AdvancedVanish.instance!!.dataFolder.toString() + File.separator, "config.yml").also { if (it.exists()) { val backupFile = File(AdvancedVanish.instance!!.dataFolder.toString() + File.separator, "config-backup-${System.currentTimeMillis()}.yml") @@ -70,7 +77,11 @@ object Config { val oldYamlConfig = YamlConfiguration().also { config -> config.load(backupFile) } for (key in oldYamlConfig.getKeys(false)) { - checkKeys(plugin.config, oldYamlConfig, key) + checkKeys(currentConfigVersion, CONFIG_VERSION!!, plugin.config, oldYamlConfig, key) + } + + if (currentConfigVersion < 8) { + AdvancedVanish.log(Level.INFO, "Config messages have been updated to use the MiniMessage formatting. Please check your config.yml for more information.") } (plugin.config as YamlConfiguration).options().width(120) @@ -80,27 +91,33 @@ object Config { } } - AdvancedVanish.log(Level.WARNING, "WARNING: Config version mismatch, a backup of the old config has been made and the current config has been replaced.") + AdvancedVanish.log(Level.INFO, "Config version mismatch (most likely because of an update), a backup of the old config has been made and the current config has been replaced.") this.reload() return } this.reloadMessages() this.reloadCommandHandlerMessages() + ServerSyncManager.setup() VanishStateManager.onConfigReload() this.usingPriorities = this.getValueOrDefault("priority.enable", false) } - private fun checkKeys(newYamlConfig: FileConfiguration, oldYamlConfig: YamlConfiguration, currKey: String) { + private fun checkKeys(oldVersion: Int, newVersion: Int, newYamlConfig: FileConfiguration, oldYamlConfig: YamlConfiguration, currKey: String) { if (currKey == "config-version") return if (oldYamlConfig.isConfigurationSection(currKey)) { for (key in oldYamlConfig.getConfigurationSection(currKey)!!.getKeys(false)) { - checkKeys(newYamlConfig, oldYamlConfig, "${currKey}.${key}") + checkKeys(oldVersion, newVersion, newYamlConfig, oldYamlConfig, "${currKey}.${key}") } } else { if (newYamlConfig.contains(currKey) && oldYamlConfig.contains(currKey) && newYamlConfig.get(currKey)!!::class == oldYamlConfig.get(currKey)!!::class) { - newYamlConfig.set(currKey, oldYamlConfig.get(currKey)) + // update formatting to use MiniMessage + if (newYamlConfig.get(currKey)!! is String && oldVersion < 8) { + newYamlConfig.set(currKey, MiniMessage.miniMessage().serialize(LegacyComponentSerializer.legacyAmpersand().deserialize(oldYamlConfig.get(currKey) as String))) + } else { + newYamlConfig.set(currKey, oldYamlConfig.get(currKey)) + } } } } @@ -132,31 +149,31 @@ object Config { } private fun getMessage(key: String): List { - return messages[key] ?: listOf("&7Message not found for &c$key&7.".color()) + return messages[key] ?: listOf("Message not found for $key.") } private fun getMessage(key: String, vararg pairs: Pair): List { - return messages[key]?.applyPlaceholders(*pairs) ?: listOf("&7Message not found for &c$key&7.".color()) + return messages[key]?.applyPlaceholders(*pairs) ?: listOf("Message not found for $key.") } fun sendMessage(player: CommandSender, key: String) { var prefix = "" if (this.getValueOrDefault("messages.prefix.enabled", false)) { - prefix = this.getValueOrDefault("messages.prefix.value", "&c[AdvancedVanish]&f ").color() + prefix = this.getValueOrDefault("messages.prefix.value", "[AdvancedVanish] ") } - this.getMessage(key).filter { it.isNotEmpty() }.forEach { player.sendMessage(prefix + it) } + this.getMessage(key).filter { it.isNotEmpty() }.forEach { player.sendComponentMessage(prefix.color().append(it.color())) } } - fun sendMessage(player: CommandSender, key: String, vararg pairs: Pair) { - var prefix = "" + fun sendMessage(sender: CommandSender, key: String, vararg pairs: Pair) { + var prefix: Component = Component.text("") if (this.getValueOrDefault("messages.prefix.enabled", false)) { - prefix = this.getValueOrDefault("messages.prefix.value", "&c[AdvancedVanish]&f ").color() + prefix = this.getValueOrDefault("messages.prefix.value", "[AdvancedVanish] ").color() } - this.getMessage(key, *pairs).filter { it.isNotEmpty() }.forEach { player.sendMessage(prefix + it) } + this.getMessage(key, *pairs).filter { it.isNotEmpty() }.forEach { sender.sendComponentMessage(prefix.append(it.color())) } } private fun reloadMessages() { @@ -165,9 +182,9 @@ object Config { this.savedConfig?.getConfigurationSection("messages")?.let { it.getKeys(false).forEach { key -> if (it.isString(key)) { - messages[key] = listOf(it.getString(key)!!).map(String::color) + messages[key] = listOf(it.getString(key)!!) } else if (it.isList(key)) { - messages[key] = it.getList(key)!!.filterIsInstance().map(String::color) + messages[key] = it.getList(key)!!.filterIsInstance() } } } @@ -179,34 +196,44 @@ object Config { this.savedConfig?.getConfigurationSection("command-handler-messages")?.let { it.getKeys(false).forEach { key -> if (it.isString(key)) { - commandHandlerMessages[key] = it.getString(key)!!.color() + commandHandlerMessages[key] = it.getString(key)!! } } } val prefix = if (this.savedConfig?.getConfigurationSection("command-handler-messages")?.getBoolean("use-prefix")!!) { - this.getValueOrDefault("messages.prefix.value", "&c[AdvancedVanish]&f ").color() + this.getValueOrDefault("messages.prefix.value", "[AdvancedVanish] ") } else { "" } val getOrDefault: (String, String) -> String = { key, default -> - prefix + if (commandHandlerMessages.containsKey(key)) commandHandlerMessages[key]!!.color() else default.color() + prefix + if (commandHandlerMessages.containsKey(key)) commandHandlerMessages[key]!! else default } val messages: MutableMap = Maps.newHashMap() + messages[MessageKeys.UNKNOWN_COMMAND] = getOrDefault("unknown-command", "Invalid arguments.") - messages[MessageKeys.INVALID_SYNTAX] = getOrDefault("invalid-syntax", "Usage: %command% %syntax%").applyPlaceholders( - "%command%" to "{command}", - "%syntax%" to "{syntax}" - ) + .color().colorLegacy() + + messages[MessageKeys.INVALID_SYNTAX] = getOrDefault("invalid-syntax", "Usage: %command% %syntax%") + .applyPlaceholders( + "%command%" to "{command}", + "%syntax%" to "{syntax}" + ) + .color().colorLegacy() + messages[MessageKeys.ERROR_PERFORMING_COMMAND] = getOrDefault("error-performing-command", "There was an error performing this command.") - messages[MessageKeys.COULD_NOT_FIND_PLAYER] = getOrDefault("could-not-find-player", "Couldn't find a player by the name of &c%search%&f.").applyPlaceholders( - "%search%" to "{search}" - ) - messages[MessageKeys.ERROR_PREFIX] = getOrDefault("generic-error", "Error: &c%error%").applyPlaceholders( - "%error%" to "{message}" - ) + .color().colorLegacy() + + messages[MessageKeys.COULD_NOT_FIND_PLAYER] = getOrDefault("could-not-find-player", "Couldn't find a player by the name of %search%.") + .applyPlaceholders("%search%" to "{search}") + .color().colorLegacy() + + messages[MessageKeys.ERROR_PREFIX] = getOrDefault("generic-error", "Error: %error%") + .applyPlaceholders("%error%" to "{message}") + .color().colorLegacy() + AdvancedVanish.commandManager!!.locales.addMessages(Locales.ENGLISH, messages) } } \ No newline at end of file diff --git a/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerUnVanishEvent.kt b/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerUnVanishEvent.kt index b28ceab..66b8f23 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerUnVanishEvent.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerUnVanishEvent.kt @@ -4,7 +4,7 @@ import org.bukkit.entity.Player import org.bukkit.event.Event import org.bukkit.event.HandlerList -class PlayerUnVanishEvent(val player: Player) : Event() { +class PlayerUnVanishEvent(val player: Player, val onLeave: Boolean) : Event() { companion object { val HANDLERS = HandlerList() diff --git a/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerVanishEvent.kt b/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerVanishEvent.kt index e042bf1..426e396 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerVanishEvent.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/event/PlayerVanishEvent.kt @@ -5,7 +5,7 @@ import org.bukkit.entity.Player import org.bukkit.event.Event import org.bukkit.event.HandlerList -class PlayerVanishEvent(val player: Player) : Event() { +class PlayerVanishEvent(val player: Player, val onJoin: Boolean) : Event() { companion object { val HANDLERS = HandlerList() diff --git a/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerUnVanishEvent.kt b/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerUnVanishEvent.kt index 5ddeeec..2aeffe0 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerUnVanishEvent.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerUnVanishEvent.kt @@ -6,7 +6,7 @@ import org.bukkit.event.Cancellable import org.bukkit.event.Event import org.bukkit.event.HandlerList -class PrePlayerUnVanishEvent(val player: Player) : Event(), Cancellable { +class PrePlayerUnVanishEvent(val player: Player, val fromLeave: Boolean) : Event(), Cancellable { companion object { val HANDLERS = HandlerList() diff --git a/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerVanishEvent.kt b/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerVanishEvent.kt index 405499c..4f32af6 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerVanishEvent.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/event/PrePlayerVanishEvent.kt @@ -6,7 +6,7 @@ import org.bukkit.event.Cancellable import org.bukkit.event.Event import org.bukkit.event.HandlerList -class PrePlayerVanishEvent(val player: Player) : Event(), Cancellable { +class PrePlayerVanishEvent(val player: Player, val onJoin: Boolean) : Event(), Cancellable { companion object { val HANDLERS = HandlerList() diff --git a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/ActionBarHook.kt b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/ActionBarHook.kt index 42d2acb..f8b352d 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/ActionBarHook.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/ActionBarHook.kt @@ -1,6 +1,5 @@ package me.quantiom.advancedvanish.hook.impl -import com.connorlinfoot.actionbarapi.ActionBarAPI import me.quantiom.advancedvanish.AdvancedVanish import me.quantiom.advancedvanish.config.Config import me.quantiom.advancedvanish.event.PlayerUnVanishEvent @@ -8,14 +7,9 @@ import me.quantiom.advancedvanish.event.PlayerVanishEvent import me.quantiom.advancedvanish.hook.IHook import me.quantiom.advancedvanish.util.AdvancedVanishAPI import me.quantiom.advancedvanish.util.color -import me.quantiom.advancedvanish.util.isVanished -import net.md_5.bungee.api.ChatMessageType -import net.md_5.bungee.api.chat.TextComponent import org.bukkit.Bukkit import org.bukkit.entity.Player import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority -import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.scheduler.BukkitRunnable class ActionBarHook : IHook { @@ -37,16 +31,11 @@ class ActionBarHook : IHook { } private fun sendActionBar(player: Player) { - this.sendActionBarStr(player, Config.getValueOrDefault("messages.action-bar", "&cYou are in vanish.")) + this.sendActionBarStr(player, Config.getValueOrDefault("messages.action-bar", "You are in vanish.")) } private fun sendActionBarStr(player: Player, str: String) { - try { - Class.forName("net.md_5.bungee.api.ChatMessageType") - player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent(str.color())) - } catch (e: ClassNotFoundException) { - ActionBarAPI.sendActionBar(player, str.color()) - } + AdvancedVanish.adventure?.player(player)?.sendActionBar(str.color()) } @EventHandler diff --git a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/DiscordSrvHook.kt b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/DiscordSrvHook.kt index fddf704..db2d2c9 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/DiscordSrvHook.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/DiscordSrvHook.kt @@ -1,8 +1,55 @@ package me.quantiom.advancedvanish.hook.impl +import github.scarsz.discordsrv.DiscordSRV +import me.quantiom.advancedvanish.AdvancedVanish +import me.quantiom.advancedvanish.config.Config +import me.quantiom.advancedvanish.event.PlayerUnVanishEvent +import me.quantiom.advancedvanish.event.PlayerVanishEvent +import me.quantiom.advancedvanish.hook.HooksManager import me.quantiom.advancedvanish.hook.IHook +import me.quantiom.advancedvanish.util.AdvancedVanishAPI +import me.quantiom.advancedvanish.util.applyPlaceholders +import me.quantiom.advancedvanish.util.color +import me.quantiom.advancedvanish.util.colorLegacy +import org.bukkit.event.EventHandler +import org.bukkit.metadata.FixedMetadataValue -// Implementation is in VanishUtil#vanishPlayer and VanishUtil#unVanishPlayer class DiscordSrvHook : IHook { override fun getID() = "DiscordSrv" + + // DiscordSRV uses the "vanished" metadata to check if a player is + // vanished (https://github.com/DiscordSRV/DiscordSRV/blob/master/src/main/java/github/scarsz/discordsrv/DiscordSRV.java#L1202-L1224) + // This avoids sending double join and leave messages on discord (for fake vanish messages) + + @EventHandler + private fun onVanish(event: PlayerVanishEvent) { + event.player.setMetadata("vanished", FixedMetadataValue(AdvancedVanish.instance!!, true)) + + if (!event.onJoin && Config.getValueOrDefault("join-leave-messages.fake-leave-message-on-vanish.enable", false)) { + val message = Config.getValueOrDefault( + "join-leave-messages.fake-leave-message-on-vanish.message", + "%player-name% has left the game." + ).applyPlaceholders( + "%player-name%" to event.player.name + ).color() + + DiscordSRV.getPlugin().sendLeaveMessage(event.player, message.colorLegacy()) + } + } + + @EventHandler + private fun onUnVanish(event: PlayerUnVanishEvent) { + event.player.removeMetadata("vanished", AdvancedVanish.instance!!) + + if (!event.onLeave && Config.getValueOrDefault("join-leave-messages.fake-join-message-on-unvanish.enable", false)) { + val message = Config.getValueOrDefault( + "join-leave-messages.fake-join-message-on-unvanish.message", + "%player-name% has joined the game." + ).applyPlaceholders( + "%player-name%" to event.player.name + ).color() + + DiscordSRV.getPlugin().sendJoinMessage(event.player, message.colorLegacy()) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/EssentialsHook.kt b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/EssentialsHook.kt index 3e142df..3350569 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/EssentialsHook.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/EssentialsHook.kt @@ -14,12 +14,6 @@ class EssentialsHook : IHook { override fun getID() = "Essentials" - // remove essentials vanish - @EventHandler(priority = EventPriority.LOWEST) - private fun onJoin(event: PlayerJoinEvent) { - this.essentials.getUser(event.player).isVanished = false - } - @EventHandler private fun onVanish(event: PlayerVanishEvent) { if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) { @@ -28,7 +22,7 @@ class EssentialsHook : IHook { } @EventHandler - private fun onUnvanish(event: PlayerUnVanishEvent) { + private fun onUnVanish(event: PlayerUnVanishEvent) { if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) { this.essentials.getUser(event.player).isHidden = false } diff --git a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/PlaceHolderApiHook.kt b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/PlaceHolderApiHook.kt index 792c843..7010e5f 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/PlaceHolderApiHook.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/hook/impl/PlaceHolderApiHook.kt @@ -21,14 +21,14 @@ class PlaceHolderApiHook : IHook { override fun persist() = true override fun canRegister() = true - override fun onPlaceholderRequest(player: Player, params: String): String? { + override fun onPlaceholderRequest(player: Player?, params: String): String? { return when (params.lowercase()) { - isVanishedPlaceholder -> if (player.isVanished()) "Yes" else "No" - vanishedPlayersPlaceholder -> { - val players = AdvancedVanishAPI.vanishedPlayers.map(Bukkit::getPlayer).map { it!! }.joinToString(", ", transform = Player::getName) - - if (players.isEmpty()) "None" else players - } + isVanishedPlaceholder -> if (player?.isVanished() == true) "Yes" else "No" + vanishedPlayersPlaceholder -> AdvancedVanishAPI.vanishedPlayers + .map(Bukkit::getPlayer) + .map { it!! } + .joinToString(", ", transform = Player::getName) + .ifEmpty { "None" } playerCountPlaceholder -> (Bukkit.getOnlinePlayers().size - AdvancedVanishAPI.vanishedPlayers.size).toString() else -> null } diff --git a/src/main/kotlin/me/quantiom/advancedvanish/listener/VanishListener.kt b/src/main/kotlin/me/quantiom/advancedvanish/listener/VanishListener.kt index 64a15c7..79cacf3 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/listener/VanishListener.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/listener/VanishListener.kt @@ -1,6 +1,7 @@ package me.quantiom.advancedvanish.listener import me.quantiom.advancedvanish.config.Config +import me.quantiom.advancedvanish.sync.ServerSyncManager import me.quantiom.advancedvanish.state.VanishStateManager import me.quantiom.advancedvanish.util.AdvancedVanishAPI import me.quantiom.advancedvanish.util.isVanished @@ -41,13 +42,17 @@ object VanishListener : Listener { var doVanish = false if (player.hasPermission(vanishPermission)) { - if (Config.getValueOrDefault("keep-vanish-state", false) && VanishStateManager.savedVanishStates.containsKey(player.uniqueId)) { - if (VanishStateManager.savedVanishStates[player.uniqueId]!!) { + if (ServerSyncManager.crossServerSupportEnabled && ServerSyncManager.loginVanishStates.containsKey(player.uniqueId)) { + doVanish = ServerSyncManager.loginVanishStates[player.uniqueId]!! + } else { + if (Config.getValueOrDefault("keep-vanish-state", false) && VanishStateManager.savedVanishStates.containsKey(player.uniqueId)) { + if (VanishStateManager.savedVanishStates[player.uniqueId]!!) { + doVanish = true + VanishStateManager.savedVanishStates.remove(player.uniqueId) + } + } else if (Config.getValueOrDefault("vanish-on-join", false) || player.hasPermission(joinVanishedPermission)) { doVanish = true - VanishStateManager.savedVanishStates.remove(player.uniqueId) } - } else if (Config.getValueOrDefault("vanish-on-join", false) || player.hasPermission(joinVanishedPermission)) { - doVanish = true } } @@ -79,7 +84,7 @@ object VanishListener : Listener { } if (!Config.getValueOrDefault("when-vanished.leave-messages", false)) { - if (AdvancedVanishAPI.isPlayerVanished(player)) { + if (isVanished) { event.quitMessage = null } } diff --git a/src/main/kotlin/me/quantiom/advancedvanish/state/VanishStateManager.kt b/src/main/kotlin/me/quantiom/advancedvanish/state/VanishStateManager.kt index 802a922..3129ad8 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/state/VanishStateManager.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/state/VanishStateManager.kt @@ -52,7 +52,7 @@ object VanishStateManager { } fun canInteract(player: Player): Boolean { - return this.interactEnabled.contains(player.uniqueId); + return this.interactEnabled.contains(player.uniqueId) } private fun getFile(): File? { diff --git a/src/main/kotlin/me/quantiom/advancedvanish/sync/IServerSyncStore.kt b/src/main/kotlin/me/quantiom/advancedvanish/sync/IServerSyncStore.kt new file mode 100644 index 0000000..4901e77 --- /dev/null +++ b/src/main/kotlin/me/quantiom/advancedvanish/sync/IServerSyncStore.kt @@ -0,0 +1,11 @@ +package me.quantiom.advancedvanish.sync + +import java.util.* + +interface IServerSyncStore { + fun setup(): Boolean + fun close() + + fun get(key: UUID): Boolean + fun setAsync(key: UUID, value: Boolean) +} \ No newline at end of file diff --git a/src/main/kotlin/me/quantiom/advancedvanish/sync/ServerSyncManager.kt b/src/main/kotlin/me/quantiom/advancedvanish/sync/ServerSyncManager.kt new file mode 100644 index 0000000..9f861be --- /dev/null +++ b/src/main/kotlin/me/quantiom/advancedvanish/sync/ServerSyncManager.kt @@ -0,0 +1,69 @@ +package me.quantiom.advancedvanish.sync + +import com.google.common.collect.Maps +import me.quantiom.advancedvanish.AdvancedVanish +import me.quantiom.advancedvanish.config.Config +import me.quantiom.advancedvanish.event.PlayerUnVanishEvent +import me.quantiom.advancedvanish.event.PlayerVanishEvent +import me.quantiom.advancedvanish.sync.impl.RedisServerSyncStore +import me.quantiom.advancedvanish.sync.impl.SqlServerSyncStore +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.AsyncPlayerPreLoginEvent +import java.util.* +import java.util.logging.Level + +object ServerSyncManager : Listener { + var crossServerSupportEnabled: Boolean = false + var serverSyncStoreImpl: IServerSyncStore? = null + + var loginVanishStates: MutableMap = Maps.newHashMap() + + fun setup() { + if (Config.getValueOrDefault("cross-server-support.enabled", false)) { + serverSyncStoreImpl = when (Config.getValueOrDefault("cross-server-support.mode", "redis").lowercase()) { + "redis" -> RedisServerSyncStore + "sql" -> SqlServerSyncStore + else -> { + AdvancedVanish.log(Level.WARNING, "Invalid mode set for cross-server-support. Please double check your config.") + return + } + } + + this.crossServerSupportEnabled = serverSyncStoreImpl!!.setup() + } else { + // if the cross-server-support option gets disabled when reloading + this.serverSyncStoreImpl?.close() + this.crossServerSupportEnabled = false + } + } + + fun close() { + this.serverSyncStoreImpl?.close() + } + + @EventHandler + fun onAsyncJoin(event: AsyncPlayerPreLoginEvent) { + this.get(event.uniqueId).let { + this.loginVanishStates.put(event.uniqueId, it) + } + } + + @EventHandler(ignoreCancelled = true) + fun onVanish(event: PlayerVanishEvent) = + run { if (!event.onJoin) this.setAsync(event.player.uniqueId, true) } + + @EventHandler(ignoreCancelled = true) + fun onUnVanish(event: PlayerUnVanishEvent) = + run { if (!event.onLeave) this.setAsync(event.player.uniqueId, false) } + + fun get(key: UUID): Boolean { + if (!this.crossServerSupportEnabled) return false + return this.serverSyncStoreImpl?.get(key)!! + } + + private fun setAsync(key: UUID, value: Boolean) { + if (!this.crossServerSupportEnabled) return + this.serverSyncStoreImpl?.setAsync(key, value) + } +} \ No newline at end of file diff --git a/src/main/kotlin/me/quantiom/advancedvanish/sync/impl/RedisServerSyncStore.kt b/src/main/kotlin/me/quantiom/advancedvanish/sync/impl/RedisServerSyncStore.kt new file mode 100644 index 0000000..d163b6b --- /dev/null +++ b/src/main/kotlin/me/quantiom/advancedvanish/sync/impl/RedisServerSyncStore.kt @@ -0,0 +1,69 @@ +package me.quantiom.advancedvanish.sync.impl + +import me.quantiom.advancedvanish.AdvancedVanish +import me.quantiom.advancedvanish.config.Config +import me.quantiom.advancedvanish.sync.IServerSyncStore +import org.bukkit.Bukkit +import redis.clients.jedis.JedisPool +import java.util.* +import java.util.logging.Level + +object RedisServerSyncStore : IServerSyncStore { + private var pool: JedisPool? = null + + override fun setup(): Boolean { + this.pool = JedisPool( + Config.getValueOrDefault("cross-server-support.redis.ip", "127.0.0.1"), + Config.getValueOrDefault("cross-server-support.redis.port", 6379), + null, + Config.getValueOrDefault("cross-server-support.redis.auth", "").ifEmpty { null }, + ) + + try { + this.pool!!.resource?.get("test") + } catch (e: Exception) { + AdvancedVanish.log(Level.SEVERE, "There was an error while attempting to make a connection with Redis: ") + e.printStackTrace() + return false + } + + AdvancedVanish.log(Level.INFO, "Successfully connected to Redis.") + return true + } + + override fun close() { + this.pool?.close() + } + + override fun get(key: UUID): Boolean { + var returnValue: String? = null + + try { + this.pool?.resource?.let { resource -> + returnValue = resource.get(this.getPlayerKey(key)) + resource.close() + } + } catch (e: Exception) { + AdvancedVanish.log(Level.SEVERE, "There was an error while attempting to make a connection with Redis: ") + e.printStackTrace() + } + + return returnValue?.let { it == "true" } ?: false + } + + override fun setAsync(key: UUID, value: Boolean) { + Bukkit.getScheduler().runTaskAsynchronously(AdvancedVanish.instance!!, Runnable { + try { + this.pool?.resource?.let { resource -> + resource.set(this.getPlayerKey(key), value.toString()) + resource.close() + } + } catch (e: Exception) { + AdvancedVanish.log(Level.SEVERE, "There was an error while attempting to make a connection with Redis: ") + e.printStackTrace() + } + }) + } + + private fun getPlayerKey(uuid: UUID) = "advancedvanish-${uuid}" +} \ No newline at end of file diff --git a/src/main/kotlin/me/quantiom/advancedvanish/sync/impl/SqlServerSyncStore.kt b/src/main/kotlin/me/quantiom/advancedvanish/sync/impl/SqlServerSyncStore.kt new file mode 100644 index 0000000..473ab3f --- /dev/null +++ b/src/main/kotlin/me/quantiom/advancedvanish/sync/impl/SqlServerSyncStore.kt @@ -0,0 +1,90 @@ +package me.quantiom.advancedvanish.sync.impl + +import me.quantiom.advancedvanish.AdvancedVanish +import me.quantiom.advancedvanish.config.Config +import me.quantiom.advancedvanish.sync.IServerSyncStore +import org.bukkit.Bukkit +import org.jetbrains.exposed.dao.id.IntIdTable +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.transactions.transaction +import java.util.* +import java.util.logging.Level + +object SqlServerSyncStore : IServerSyncStore { + private var database: Database? = null + + object AdvancedVanishTable : IntIdTable() { + val uuid: Column = varchar("uuid", 36) + val state: Column = bool("state") + } + + override fun setup(): Boolean { + val host = Config.getValueOrDefault("cross-server-support.sql.ip", "127.0.0.1") + val port = Config.getValueOrDefault("cross-server-support.sql.port", 3306) + val username = Config.getValueOrDefault("cross-server-support.sql.username", "root") + val password = Config.getValueOrDefault("cross-server-support.sql.password", "") + val database = Config.getValueOrDefault("cross-server-support.sql.database", "minecraft") + + this.database = Database.connect( + "jdbc:mysql://$host:$port/$database", + driver = "com.mysql.cj.jdbc.Driver", + user = username, + password = password + ) + + try { + transaction { + if (!AdvancedVanishTable.exists()) { + SchemaUtils.create(AdvancedVanishTable) + } + } + } catch (e: Exception) { + AdvancedVanish.log(Level.SEVERE, "There was an error while attempting to make a connection with SQL: ") + e.printStackTrace() + return false + } + + AdvancedVanish.log(Level.INFO, "Successfully connected to the SQL database.") + return true + } + + override fun close() { + // doesn't need to be closed from what I can tell + } + + override fun get(key: UUID): Boolean { + try { + return transaction { + return@transaction AdvancedVanishTable.select { AdvancedVanishTable.uuid eq key.toString() } + .singleOrNull()?.getOrNull(AdvancedVanishTable.state) == true + } + } catch (e: Exception) { + AdvancedVanish.log(Level.SEVERE, "There was an error while attempting to make a connection with SQL: ") + e.printStackTrace() + } + + return false + } + + override fun setAsync(key: UUID, value: Boolean) { + Bukkit.getScheduler().runTaskAsynchronously(AdvancedVanish.instance!!, Runnable { + try { + transaction { + AdvancedVanishTable.select { AdvancedVanishTable.uuid eq key.toString() }.singleOrNull()?.getOrNull(AdvancedVanishTable.id)?.let { id -> + AdvancedVanishTable.update ({ AdvancedVanishTable.id eq id }) { + it[state] = value + } + } ?: run { + AdvancedVanishTable.insert { + it[uuid] = key.toString() + it[state] = value + } + } + } + } catch (e: Exception) { + AdvancedVanish.log(Level.SEVERE, "There was an error while attempting to make a connection with SQL: ") + e.printStackTrace() + } + }) + } +} \ No newline at end of file diff --git a/src/main/kotlin/me/quantiom/advancedvanish/util/AdvancedVanishAPI.kt b/src/main/kotlin/me/quantiom/advancedvanish/util/AdvancedVanishAPI.kt index 1e809b5..3f00b2c 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/util/AdvancedVanishAPI.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/util/AdvancedVanishAPI.kt @@ -2,14 +2,12 @@ package me.quantiom.advancedvanish.util import com.google.common.collect.Lists import com.google.common.collect.Maps -import github.scarsz.discordsrv.DiscordSRV import me.quantiom.advancedvanish.AdvancedVanish import me.quantiom.advancedvanish.config.Config import me.quantiom.advancedvanish.event.PlayerUnVanishEvent import me.quantiom.advancedvanish.event.PlayerVanishEvent import me.quantiom.advancedvanish.event.PrePlayerUnVanishEvent import me.quantiom.advancedvanish.event.PrePlayerVanishEvent -import me.quantiom.advancedvanish.hook.HooksManager import me.quantiom.advancedvanish.permission.PermissionsManager import me.quantiom.advancedvanish.state.VanishStateManager import org.bukkit.Bukkit @@ -34,17 +32,16 @@ object AdvancedVanishAPI { * @param onJoin If this is being called from the PlayerJoinEvent, used for hook/fake join and leave message functionality */ fun vanishPlayer(player: Player, onJoin: Boolean = false) { - val prePlayerVanishEvent = PrePlayerVanishEvent(player) + val prePlayerVanishEvent = PrePlayerVanishEvent(player, onJoin) Bukkit.getPluginManager().callEvent(prePlayerVanishEvent) if (prePlayerVanishEvent.isCancelled) return this.vanishedPlayers.add(player.uniqueId) - + // add vanished metadata to player for other plugins to use player.setMetadata("vanished", FixedMetadataValue(AdvancedVanish.instance!!, true)) - val previousEffects: MutableList = Lists.newArrayList(); // add potion effects @@ -52,8 +49,8 @@ object AdvancedVanishAPI { .map { it.split(":") } .filter { it.size > 1 } .forEach { - PotionEffectType.values().find { e -> e.name == it[0] }?.run { - val currentPotionEffect = player.getPotionEffect(this) + PotionEffectType.values().find { e -> e?.name == it[0] }?.run { + val currentPotionEffect = player.activePotionEffects.find { e -> e.type == this } if (currentPotionEffect != null) { previousEffects.add(currentPotionEffect) @@ -61,7 +58,13 @@ object AdvancedVanishAPI { previousEffects.add(this.createEffect(0, 0)) } - player.addPotionEffect(this.createEffect(Integer.MAX_VALUE, it[1].toInt() - 1)) + if (onJoin) { + Bukkit.getScheduler().runTaskLater(AdvancedVanish.instance!!, Runnable { + player.addPotionEffect(this.createEffect(Integer.MAX_VALUE, it[1].toInt() - 1)) + }, 10L) + } else { + player.addPotionEffect(this.createEffect(Integer.MAX_VALUE, it[1].toInt() - 1)) + } } } @@ -92,23 +95,19 @@ object AdvancedVanishAPI { if (!onJoin && Config.getValueOrDefault("join-leave-messages.fake-leave-message-on-vanish.enable", false)) { val message = Config.getValueOrDefault( "join-leave-messages.fake-leave-message-on-vanish.message", - "&e%player-name% has left the game." + "%player-name% has left the game." ).applyPlaceholders( "%player-name%" to player.name ).color() - Bukkit.broadcastMessage(message) - - if (HooksManager.isHookEnabled("DiscordSrv")) { - DiscordSRV.getPlugin().sendLeaveMessage(player, message) - } + Bukkit.getOnlinePlayers().forEach { it.sendComponentMessage(message) } } if (Config.getValueOrDefault("when-vanished.fly.enable", true)) { player.allowFlight = true } - Bukkit.getPluginManager().callEvent(PlayerVanishEvent(player)) + Bukkit.getPluginManager().callEvent(PlayerVanishEvent(player, onJoin)) } /** @@ -119,7 +118,7 @@ object AdvancedVanishAPI { * @param onLeave If this is being called from the PlayerQuitEvent, used for hook/fake join and leave message functionality */ fun unVanishPlayer(player: Player, onLeave: Boolean = false) { - val prePlayerUnVanishEvent = PrePlayerUnVanishEvent(player) + val prePlayerUnVanishEvent = PrePlayerUnVanishEvent(player, onLeave) Bukkit.getPluginManager().callEvent(prePlayerUnVanishEvent) if (prePlayerUnVanishEvent.isCancelled) return @@ -158,19 +157,15 @@ object AdvancedVanishAPI { if (!onLeave && Config.getValueOrDefault("join-leave-messages.fake-join-message-on-unvanish.enable", false)) { val message = Config.getValueOrDefault( "join-leave-messages.fake-join-message-on-unvanish.message", - "&e%player-name% has joined the game." + "%player-name% has joined the game." ).applyPlaceholders( "%player-name%" to player.name ).color() - Bukkit.broadcastMessage(message) - - if (HooksManager.isHookEnabled("DiscordSrv")) { - DiscordSRV.getPlugin().sendJoinMessage(player, message) - } + Bukkit.getOnlinePlayers().forEach { it.sendComponentMessage(message) } } - Bukkit.getPluginManager().callEvent(PlayerUnVanishEvent(player)) + Bukkit.getPluginManager().callEvent(PlayerUnVanishEvent(player, onLeave)) } fun refreshVanished(player: Player) { diff --git a/src/main/kotlin/me/quantiom/advancedvanish/util/DependencyManager.java b/src/main/kotlin/me/quantiom/advancedvanish/util/DependencyManager.java new file mode 100644 index 0000000..ea38e90 --- /dev/null +++ b/src/main/kotlin/me/quantiom/advancedvanish/util/DependencyManager.java @@ -0,0 +1,74 @@ +package me.quantiom.advancedvanish.util; + +import com.google.common.collect.Lists; +import me.quantiom.advancedvanish.AdvancedVanishPlugin; +import net.byteflux.libby.BukkitLibraryManager; +import net.byteflux.libby.Library; + +import java.util.List; +import java.util.logging.Level; + +public final class DependencyManager { + private final AdvancedVanishPlugin plugin; + private final BukkitLibraryManager libraryManager; + + public DependencyManager(AdvancedVanishPlugin plugin) { + this.plugin = plugin; + this.libraryManager = new BukkitLibraryManager(plugin); + this.libraryManager.addMavenCentral(); + } + + private Library getLibrary(String groupId, String artifactId, String version, String pattern, String relocatePattern) { + Library.Builder builder = Library.builder() + .groupId(groupId) + .artifactId(artifactId) + .version(version); + + if (!relocatePattern.isEmpty()) { + builder.relocate(pattern, relocatePattern); + } + + return builder.build(); + } + + public void loadDependencies() { + this.plugin.getLogger().log(Level.INFO, "Loading dependencies..."); + + // this is very weird, but I think without a way to exclude specific files/classes from + // being replaced by the shade plugin, this would be the only way to not have the string "kotlin" replaced + String kotlinStr = "ko"; + kotlinStr += "tlin"; + + List libraries = Lists.newArrayList( + // exposed + this.getLibrary("org{}jetbrains{}exposed", "exposed-core", "0.39.2", "org{}jetbrains{}exposed", "me{}quantiom{}advancedvanish{}shaded{}exposed"), + this.getLibrary("org{}jetbrains{}exposed", "exposed-dao", "0.39.2", "org{}jetbrains{}exposed", "me{}quantiom{}advancedvanish{}shaded{}exposed"), + this.getLibrary("org{}jetbrains{}exposed", "exposed-jdbc", "0.39.2", "org{}jetbrains{}exposed", "me{}quantiom{}advancedvanish{}shaded{}exposed"), + // redis + this.getLibrary("redis{}clients", "jedis", "4.2.0", "", ""), + this.getLibrary("org{}apache{}commons", "commons-pool2", "2.11.1", "", ""), + this.getLibrary("org{}json", "json", "20211205", "", ""), + // adventure + this.getLibrary("net{}kyori", "adventure-api", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-platform-api", "4.1.2", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-platform-bukkit", "4.1.2", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-platform-facet", "4.1.2", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-text-serializer-bungeecord", "4.1.2", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-text-serializer-legacy", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-nbt", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-text-serializer-gson", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-text-serializer-gson-legacy-impl", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-platform-viaversion", "4.1.2", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-key", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + this.getLibrary("net{}kyori", "adventure-text-minimessage", "4.11.0", "net{}kyori{}adventure", "me{}quantiom{}advancedvanish{}shaded{}adventure"), + // kotlin + this.getLibrary("org{}jetbrains{}" + kotlinStr, kotlinStr + "-stdlib", "1.7.10", kotlinStr, "me.quantiom.advancedvanish.shaded.kotlin") + ); + + for (Library library : libraries) { + this.libraryManager.loadLibrary(library); + } + + this.plugin.getLogger().log(Level.INFO, "Successfully loaded dependencies."); + } +} diff --git a/src/main/kotlin/me/quantiom/advancedvanish/util/Extensions.kt b/src/main/kotlin/me/quantiom/advancedvanish/util/Extensions.kt index 80c01fc..f0897bc 100644 --- a/src/main/kotlin/me/quantiom/advancedvanish/util/Extensions.kt +++ b/src/main/kotlin/me/quantiom/advancedvanish/util/Extensions.kt @@ -1,10 +1,12 @@ package me.quantiom.advancedvanish.util +import me.quantiom.advancedvanish.AdvancedVanish import me.quantiom.advancedvanish.config.Config -import org.bukkit.ChatColor +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import org.bukkit.command.CommandSender import org.bukkit.entity.Player -import java.util.regex.Pattern fun String.applyPlaceholders(vararg pairs: Pair): String { var intermediate = this @@ -19,28 +21,17 @@ fun String.applyPlaceholders(vararg pairs: Pair): String { fun List.applyPlaceholders(vararg pairs: Pair): List = this.map { it.applyPlaceholders(*pairs) } -fun String.color(): String { - var message = this; - val pattern = Pattern.compile("#[a-fA-F0-9]{6}") - var matcher = pattern.matcher(message) - - while (matcher.find()) { - val hexCode = message.substring(matcher.start(), matcher.end()) - val replaceSharp = hexCode.replace('#', 'x') - val ch = replaceSharp.toCharArray() - val builder = StringBuilder("") - - for (c in ch) { - builder.append("&$c") - } - - message = message.replace(hexCode, builder.toString()) - matcher = pattern.matcher(message) - } +fun String.color(): Component { + return MiniMessage.miniMessage().deserialize(this) +} - return ChatColor.translateAlternateColorCodes('&', message) +fun Component.colorLegacy(): String { + return LegacyComponentSerializer.legacyAmpersand().serialize(this) } fun CommandSender.sendConfigMessage(key: String) = Config.sendMessage(this, key) fun CommandSender.sendConfigMessage(key: String, vararg pairs: Pair) = Config.sendMessage(this, key, *pairs) -fun Player.sendColoredMessage(msg: String) = this.sendMessage(msg.color()) \ No newline at end of file +fun CommandSender.sendComponentMessage(msg: Component) = AdvancedVanish.adventure!!.sender(this).sendMessage(msg) + +fun Player.sendComponentMessage(msg: Component) = AdvancedVanish.adventure!!.player(this).sendMessage(msg) +fun Player.sendColoredMessage(msg: String) = this.sendComponentMessage(msg.color()) \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f8fe7b2..98e28f9 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -7,9 +7,17 @@ ################################################################################### # Made by quantiom, config made for v%PROJECT_VERSION% +# GitBook page: https://quantioms.gitbook.io/advancedvanish/ + +# Messages in this config use MiniMessage formatting +# For example, the message "&4Hello &a&lWorld" would need to be "Hello World" +# Please check the documentation for more information: https://docs.adventure.kyori.net/minimessage/format.html + # Automatically check for updates check-for-updates: true +# WARNING: The three following options will be IGNORED if cross-server-support is enabled + # Enable vanish on join vanish-on-join: true # Saves the vanish state when a player logs off @@ -21,6 +29,24 @@ keep-vanish-state: false # persist outside of server restarts keep-vanish-state-persistent: false +# Cross-server vanish synchronization +# Requires Redis or SQL +cross-server-support: + enabled: false + # Either "redis" or "sql" + mode: "redis" + redis: + ip: "127.0.0.1" + port: 6379 + auth: "" + sql: + ip: "127.0.0.1" + port: 3306 + username: "root" + password: "" + database: "minecraft" + table-prefix: "advancedvanish_" + # Actions when players are vanished # true = enabled, false = disabled when-vanished: @@ -68,12 +94,12 @@ join-leave-messages: enable: false # Placeholders: # %priority% - The player's vanish priority - message: "&e%player-name% has joined the game" + message: "%player-name% has joined the game" fake-leave-message-on-vanish: enable: false # Placeholders: # %player-name% - The player's name - message: "&e%player-name% has left the game." + message: "%player-name% has left the game." # Hooks that will add support to other plugins # Some hooks will not be enabled if the required plugin(s) are not found @@ -87,7 +113,7 @@ hooks: placeholders: true # Shows a message above the hotbar if a player is vanished # The configurable message is in the messages section below. - # Does NOT require ActionBarAPI if you are running 1.16+ + # Does NOT require or use ActionBarAPI actionbar: true # Requires DiscordSRV, sends a fake leave and join message when vanished/unvanished # and also requires the fake-join-message-on-unvanish / fake-leave-message-on-vanish to be @@ -143,12 +169,12 @@ messages: # Set/enable a prefix used before all messages prefix: enabled: true - value: "&c[AdvancedVanish]&f " - no-permission: "&cYou do not have permission to use this command." + value: "[AdvancedVanish] " + no-permission: "You do not have permission to use this command." config-reloaded: "Successfully reloaded the config." # Placeholders: # %version% - The plugin version - version-command: "This server is running AdvancedVanish &c%version%&f by quantiom" + version-command: "This server is running AdvancedVanish %version% by quantiom" vanish-on: "You are now in vanish." vanish-off: "You are no longer in vanish." cannot-chat-while-vanished: "You cannot chat while you are in vanish." @@ -161,50 +187,50 @@ messages: opening-container-silently: "Opening %type% silently..." # Placeholders: # %priority% - The player's vanish priority - vanish-priority: "Your vanish priority is &c%priority%&f." + vanish-priority: "Your vanish priority is %priority%." not-using-vanish-priority: "You are not using vanish priority, it can be enabled in the config." # Placeholders: # %vanished-players% - A list of vanished players, or "None" - vanished-list: "Vanished players: &c%vanished-players%" + vanished-list: "Vanished players: %vanished-players%" # Placeholders: # %target-name% - The target's username # %vanish-status% - "on" or "off" # %vanish-status-word% - "vanished" or "not vanished" - vanish-status-command: "&c%target-name%&f is currently &c%vanish-status-word%&f." + vanish-status-command: "%target-name% is currently %vanish-status-word%." # Placeholders: # %target-name% - The target's username # %vanish-status% - "on" or "off" # %vanish-status-word% - "vanished" or "not vanished" # This message is also used with the toggle command - vanish-set-other-command: "&fSet &c%target-name%'s&f vanish to &c%vanish-status%&f." + vanish-set-other-command: "Set %target-name%'s vanish to %vanish-status%." # Placeholders: # %target-name% - The target's username # %vanish-status% - "on" or "off" # %vanish-status-word% - "vanished" or "not vanished" - vanish-set-other-command-already: "&c%target-name%&f is already &c%vanish-status-word%" - must-be-vanished-to-use-command: "&cYou must be vanished to use this command." + vanish-set-other-command-already: "%target-name% is already %vanish-status-word%" + must-be-vanished-to-use-command: "You must be vanished to use this command." # Placeholders: # %interact-status%" - "on" or "off" - vanish-interact-toggled: "&fYou have turned %interact-status% interacting while vanished." - action-bar: "&cYou are in vanish." - disguise-removed-because-vanish: "Your disguise has been &cremoved&f because you are in vanish" + vanish-interact-toggled: "You have turned %interact-status% interacting while vanished." + action-bar: "You are in vanish." + disguise-removed-because-vanish: "Your disguise has been removed because you are in vanish" # Messages from the command handler command-handler-messages: # Will use the prefix from the message section above before all of these messages use-prefix: true - unknown-command: "&cInvalid arguments." + unknown-command: "Invalid arguments." # Placeholders: # %command% # %syntax% - invalid-syntax: "&cUsage: %command% %syntax%" - error-performing-command: "&cThere was an error performing this command." + invalid-syntax: "Usage: %command% %syntax%" + error-performing-command: "There was an error performing this command." # Placeholders: # %search% - The given player name - could-not-find-player: "&cCouldn't find a player by the name of %search%." + could-not-find-player: "Couldn't find a player by the name of %search%." # Placeholders: # %error% - The error message - generic-error: "&cError: %error%" + generic-error: "Error: %error%" # Config version - Do NOT change this manually config-version: %CONFIG_VERSION% \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6aec4f6..3d7989c 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,7 +2,7 @@ name: ${project.name} description: ${project.description} author: quantiom version: ${project.version} -main: ${project.groupId}.${project.artifactId}.${project.name} +main: ${project.groupId}.${project.artifactId}.${project.name}Plugin softdepend: [LuckPerms, PlaceholderAPI, GroupManager, PermissionsEx, bPermissions, DiscordSRV, Dynmap, squaremap, LibsDisguises, PlayerParticles, Essentials, PlaceholderAPI, ProtocolLib] api-version: 1.13 commands: