Add anti-idle feature (Closes #21).

This commit is contained in:
Logan Gorence 2022-01-29 06:01:50 +00:00
parent 0da3202555
commit ba18fcddbc
No known key found for this signature in database
GPG Key ID: 9743CEF10935949A
5 changed files with 103 additions and 0 deletions

View File

@ -87,6 +87,7 @@ subprojects {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// Core libraries.
implementation("io.insert-koin:koin-core:3.1.4")
testImplementation("io.insert-koin:koin-test:3.1.4")

View File

@ -3,4 +3,5 @@ dependencies {
implementation("software.amazon.awssdk:s3:2.17.102")
implementation("org.quartz-scheduler:quartz:2.3.2")
implementation("com.google.guava:guava:31.0.1-jre")
}

View File

@ -0,0 +1,17 @@
package cloud.kubelet.foundation.core.features.player
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PlayerConfig(
@SerialName("anti-idle")
val antiIdle: AntiIdleConfig = AntiIdleConfig(),
)
@Serializable
data class AntiIdleConfig(
val enabled: Boolean = false,
val idleDuration: Int = 3600,
val ignore: List<String> = listOf(),
)

View File

@ -1,14 +1,88 @@
package cloud.kubelet.foundation.core.features.player
import cloud.kubelet.foundation.core.FoundationCorePlugin
import cloud.kubelet.foundation.core.Util
import cloud.kubelet.foundation.core.abstraction.Feature
import com.charleskorn.kaml.Yaml
import com.google.common.cache.Cache
import com.google.common.cache.CacheBuilder
import com.google.common.cache.RemovalCause
import net.kyori.adventure.text.Component
import org.bukkit.GameMode
import org.bukkit.event.EventHandler
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerKickEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.koin.core.component.inject
import java.time.Duration
import kotlin.io.path.inputStream
class PlayerFeature : Feature() {
private val config by inject<PlayerConfig>()
private lateinit var playerActivity: Cache<String, String>
override fun enable() {
playerActivity = CacheBuilder.newBuilder()
.expireAfterWrite(Duration.ofSeconds(config.antiIdle.idleDuration.toLong()))
.removalListener<String, String> z@{
if (!config.antiIdle.enabled) return@z
if (it.cause == RemovalCause.EXPIRED) {
if (!config.antiIdle.ignore.contains(it.key!!)) {
plugin.server.scheduler.runTask(plugin) { ->
plugin.server.getPlayer(it.key!!)
?.kick(Component.text("Kicked for idling"), PlayerKickEvent.Cause.IDLING)
}
}
}
}.build()
// Expire player activity tokens occasionally.
plugin.server.scheduler.scheduleSyncRepeatingTask(plugin, {
playerActivity.cleanUp()
}, 20, 100)
registerCommandExecutor(listOf("survival", "s"), GamemodeCommand(GameMode.SURVIVAL))
registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE))
registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE))
registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR))
registerCommandExecutor(listOf("localweather", "lw"), LocalWeatherCommand())
}
override fun module() = org.koin.dsl.module {
single {
val configPath = Util.copyDefaultConfig<FoundationCorePlugin>(
plugin.slF4JLogger,
plugin.pluginDataPath,
"player.yaml",
)
return@single Yaml.default.decodeFromStream(
PlayerConfig.serializer(),
configPath.inputStream()
)
}
}
@EventHandler
private fun onPlayerJoin(e: PlayerJoinEvent) {
if (!config.antiIdle.enabled) return
playerActivity.put(e.player.name, e.player.name)
}
@EventHandler
private fun onPlayerQuit(e: PlayerQuitEvent) {
if (!config.antiIdle.enabled) return
playerActivity.invalidate(e.player.name)
}
@EventHandler
private fun onPlayerMove(e: PlayerMoveEvent) {
if (!config.antiIdle.enabled) return
if (e.hasChangedPosition() || e.hasChangedOrientation()) {
playerActivity.put(e.player.name, e.player.name)
}
}
}

View File

@ -0,0 +1,10 @@
# Kicks players idle for longer than a set amount of time.
anti-idle:
# Whether anti-idle kicking is enabled.
enabled: false
# Number of seconds the player is idle before kick.
idleDuration: 3600
# List of usernames to ignore.
ignore: []