diff --git a/sayanvanish-api/src/main/kotlin/org/sayandev/sayanvanish/api/feature/Configurable.kt b/sayanvanish-api/src/main/kotlin/org/sayandev/sayanvanish/api/feature/Configurable.kt new file mode 100644 index 00000000..7966169d --- /dev/null +++ b/sayanvanish-api/src/main/kotlin/org/sayandev/sayanvanish/api/feature/Configurable.kt @@ -0,0 +1,5 @@ +package org.sayandev.sayanvanish.api.feature + +@Target(AnnotationTarget.FIELD) +@Retention(AnnotationRetention.RUNTIME) +annotation class Configurable \ No newline at end of file diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/command/SayanVanishCommand.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/command/SayanVanishCommand.kt index 2ca4a4a5..660a887d 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/command/SayanVanishCommand.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/command/SayanVanishCommand.kt @@ -9,6 +9,7 @@ import org.sayandev.sayanvanish.api.SayanVanishAPI import org.sayandev.sayanvanish.api.VanishOptions import org.sayandev.sayanvanish.api.database.DatabaseConfig import org.sayandev.sayanvanish.api.database.databaseConfig +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.Features import org.sayandev.sayanvanish.api.feature.RegisteredFeatureHandler import org.sayandev.sayanvanish.api.utils.Paste @@ -33,11 +34,13 @@ import org.sayandev.stickynote.lib.incendo.cloud.bukkit.parser.OfflinePlayerPars import org.sayandev.stickynote.lib.incendo.cloud.component.CommandComponent import org.sayandev.stickynote.lib.incendo.cloud.parser.flag.CommandFlag import org.sayandev.stickynote.lib.incendo.cloud.parser.standard.IntegerParser +import org.sayandev.stickynote.lib.incendo.cloud.parser.standard.StringArrayParser import org.sayandev.stickynote.lib.incendo.cloud.parser.standard.StringParser import org.sayandev.stickynote.lib.incendo.cloud.suggestion.Suggestion import org.sayandev.stickynote.lib.kyori.adventure.text.minimessage.tag.resolver.Placeholder import java.io.File import java.util.concurrent.CompletableFuture +import kotlin.reflect.full.memberProperties class SayanVanishCommand : StickyCommand("sayanvanish", "vanish", "v") { @@ -246,6 +249,69 @@ class SayanVanishCommand : StickyCommand("sayanvanish", "vanish", "v") { sender.sendMessage(language.feature.featureEnabled.component(Placeholder.unparsed("feature", feature.id))) } .build()) + + manager.command(featureLiteral + .literal("update") + .permission(constructBasePermission("feature.update")) + .required( + "option", + CommandComponent.builder("state", StringParser.stringParser()) + .suggestionProvider { context, _ -> + val feature = Features.features.find { it.id == context.get("feature") } ?: return@suggestionProvider CompletableFuture.completedFuture(emptyList()) + CompletableFuture.completedFuture(feature::class.java.declaredFields.filter { it.isAnnotationPresent(Configurable::class.java) }.map { Suggestion.suggestion(it.name) }) + } + ) + .required("value", + CommandComponent.builder("value", StringParser.stringParser(StringParser.StringMode.QUOTED)) + .suggestionProvider { context, _ -> + val feature = Features.features.find { it.id == context.get("feature") } ?: let { + return@suggestionProvider CompletableFuture.completedFuture(emptyList()) + } + + val field = feature::class.java.declaredFields.find { it.name == context.get("option") } ?: let { + return@suggestionProvider CompletableFuture.completedFuture(emptyList()) + } + field.isAccessible = true + + when (field.type) { + Boolean::class.java -> CompletableFuture.completedFuture(listOf("true", "false").map { Suggestion.suggestion(it) }) + Int::class.java -> CompletableFuture.completedFuture(listOf("0", "1", "2", "3", "4", "5").map { Suggestion.suggestion(it) }) + Double::class.java -> CompletableFuture.completedFuture(listOf("0.0", "0.1", "0.2", "0.3", "0.4", "0.5").map { Suggestion.suggestion(it) }) + Float::class.java -> CompletableFuture.completedFuture(listOf("0.0", "0.1", "0.2", "0.3", "0.4", "0.5").map { Suggestion.suggestion(it) }) + else -> CompletableFuture.completedFuture(listOf(field.get(feature).toString()).map { Suggestion.suggestion(it) }) + } + } + ) + .handler { context -> + val sender = context.sender().bukkitSender() + val feature = Features.features.find { it.id == context.get("feature") } ?: let { + sender.sendMessage(language.feature.featureNotFound.component()) + return@handler + } + + val field = feature::class.java.declaredFields.find { it.name == context.get("option") } + if (field == null) { + sender.sendMessage(language.feature.invalidOption.component(Placeholder.unparsed("options", feature::class.memberProperties.joinToString(", ") { it.name }))) + return@handler + } + + val value = context.get("value") + field.isAccessible = true + try { + field.set(feature, value) + } catch (_: Exception) { + sender.sendMessage(language.feature.invalidValue.component(Placeholder.unparsed("values", field.type.simpleName ?: "N/A"))) + return@handler + } + feature.save() + + sender.sendMessage(language.feature.updated.component( + Placeholder.unparsed("feature", feature.id), + Placeholder.unparsed("option", field.name), + Placeholder.unparsed("state", value) + )) + } + .build()) } private fun sendPasteError(sender: CommandSender, error: Throwable?) { diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/config/LanguageConfig.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/config/LanguageConfig.kt index ed09b4f6..92a508fd 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/config/LanguageConfig.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/config/LanguageConfig.kt @@ -32,6 +32,9 @@ data class LanguageConfig( val featureDisabled: String = " has been disabled.", val alreadyDisabled: String = " is already disabled.", val alreadyEnabled: String = " is already enabled.", + val updated: String = " has been updated to .", + val invalidOption: String = "Invalid option, valid options are .", + val invalidValue: String = "Invalid value, valid values are .", ) @ConfigSerializable diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureActionbar.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureActionbar.kt index a2b48d6d..cc7afac9 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureActionbar.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureActionbar.kt @@ -2,6 +2,7 @@ package org.sayandev.sayanvanish.bukkit.feature.features import org.bukkit.event.EventHandler import org.sayandev.sayanvanish.api.Permission +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.bukkit.api.SayanVanishBukkitAPI.Companion.user import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserUnVanishEvent @@ -16,9 +17,9 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureActionbar( - val content: String = "You are currently vanished!", - val delay: Long = 20, - val period: Long = 20, + @Configurable val content: String = "You are currently vanished!", + @Configurable val delay: Long = 20, + @Configurable val period: Long = 20, ) : ListenedFeature("actionbar") { @EventHandler diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFakeMessage.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFakeMessage.kt index 1f600a89..9d6a5be8 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFakeMessage.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFakeMessage.kt @@ -3,6 +3,7 @@ package org.sayandev.sayanvanish.bukkit.feature.features import org.bukkit.event.EventHandler import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerQuitEvent +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserUnVanishEvent import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserVanishEvent @@ -17,12 +18,12 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureFakeMessage( - val sendFakeJoinMessage: Boolean = false, - val sendFakeQuitMessage: Boolean = false, - val fakeJoinMessage: String = " joined the game", - val fakeQuitMessage: String = " left the game", - val disableJoinMessageIfVanished: Boolean = true, - val disableQuitMessageIfVanished: Boolean = true, + @Configurable val sendFakeJoinMessage: Boolean = false, + @Configurable val sendFakeQuitMessage: Boolean = false, + @Configurable val fakeJoinMessage: String = " joined the game", + @Configurable val fakeQuitMessage: String = " left the game", + @Configurable val disableJoinMessageIfVanished: Boolean = true, + @Configurable val disableQuitMessageIfVanished: Boolean = true, ) : ListenedFeature("fake_message") { @EventHandler diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFly.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFly.kt index 1fbce5c8..f1c3e9d3 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFly.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureFly.kt @@ -2,6 +2,7 @@ package org.sayandev.sayanvanish.bukkit.feature.features import org.bukkit.event.EventHandler import org.sayandev.sayanvanish.api.Permission +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserUnVanishEvent import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserVanishEvent @@ -11,7 +12,7 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureFly( - val disableOnReappear: Boolean = true + @Configurable val disableOnReappear: Boolean = true ) : ListenedFeature("fly") { @EventHandler diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureInvulnerability.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureInvulnerability.kt index 405265f7..2e5e50ef 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureInvulnerability.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureInvulnerability.kt @@ -2,6 +2,7 @@ package org.sayandev.sayanvanish.bukkit.feature.features import org.bukkit.event.EventHandler import org.sayandev.sayanvanish.api.Permission +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserUnVanishEvent import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserVanishEvent @@ -11,7 +12,7 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureInvulnerability( - val disableOnReappear: Boolean = true + @Configurable val disableOnReappear: Boolean = true ) : ListenedFeature("invulnerability") { @EventHandler diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureLevel.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureLevel.kt index 60f16585..abcb9c15 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureLevel.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureLevel.kt @@ -5,6 +5,7 @@ import org.bukkit.event.EventHandler import org.bukkit.event.player.PlayerGameModeChangeEvent import org.bukkit.event.player.PlayerJoinEvent import org.sayandev.sayanvanish.api.Permission +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.bukkit.api.SayanVanishBukkitAPI import org.sayandev.sayanvanish.bukkit.api.SayanVanishBukkitAPI.Companion.user @@ -17,7 +18,7 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureLevel( - val seeAsSpectator: Boolean = true + @Configurable val seeAsSpectator: Boolean = true ): ListenedFeature("level") { @EventHandler diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureProxyVanishQueue.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureProxyVanishQueue.kt index 57163e45..3ef27ca6 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureProxyVanishQueue.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureProxyVanishQueue.kt @@ -1,5 +1,6 @@ package org.sayandev.sayanvanish.bukkit.feature.features +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.Feature import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.api.feature.category.FeatureCategories @@ -15,7 +16,7 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureProxyVanishQueue( - val checkEvery: Long = 100 + @Configurable val checkEvery: Long = 100 ) : Feature("proxy_vanish_queue", category = FeatureCategories.PROXY) { override fun enable() { diff --git a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureUpdateChecker.kt b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureUpdateChecker.kt index 8b437877..f9f899d6 100644 --- a/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureUpdateChecker.kt +++ b/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/FeatureUpdateChecker.kt @@ -4,6 +4,7 @@ import org.bukkit.Bukkit import org.bukkit.command.CommandSender import org.bukkit.event.EventHandler import org.bukkit.event.player.PlayerJoinEvent +import org.sayandev.sayanvanish.api.feature.Configurable import org.sayandev.sayanvanish.api.feature.RegisteredFeature import org.sayandev.sayanvanish.bukkit.api.event.BukkitUserUnVanishEvent import org.sayandev.sayanvanish.bukkit.feature.ListenedFeature @@ -21,9 +22,9 @@ import org.sayandev.stickynote.lib.spongepowered.configurate.objectmapping.Confi @RegisteredFeature @ConfigSerializable class FeatureUpdateChecker( - val checkEveryXMinutes: Int = 60, - val notifyPermission: String = "sayanvanish.feature.updatechecker.notify", - val notifyOnJoin: Boolean = true, + @Configurable val checkEveryXMinutes: Int = 60, + @Configurable val notifyPermission: String = "sayanvanish.feature.updatechecker.notify", + @Configurable val notifyOnJoin: Boolean = true, val content: List = listOf( "A new version of SayanVanish is available!", " - Latest release: ",