mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-03 05:30:55 +00:00
Add anti-idle feature (Closes #21).
This commit is contained in:
@ -87,6 +87,7 @@ subprojects {
|
|||||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
|
|
||||||
|
// Core libraries.
|
||||||
implementation("io.insert-koin:koin-core:3.1.4")
|
implementation("io.insert-koin:koin-core:3.1.4")
|
||||||
testImplementation("io.insert-koin:koin-test:3.1.4")
|
testImplementation("io.insert-koin:koin-test:3.1.4")
|
||||||
|
|
||||||
|
@ -3,4 +3,5 @@ dependencies {
|
|||||||
|
|
||||||
implementation("software.amazon.awssdk:s3:2.17.102")
|
implementation("software.amazon.awssdk:s3:2.17.102")
|
||||||
implementation("org.quartz-scheduler:quartz:2.3.2")
|
implementation("org.quartz-scheduler:quartz:2.3.2")
|
||||||
|
implementation("com.google.guava:guava:31.0.1-jre")
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
||||||
|
)
|
@ -1,14 +1,88 @@
|
|||||||
package cloud.kubelet.foundation.core.features.player
|
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 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.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() {
|
class PlayerFeature : Feature() {
|
||||||
|
private val config by inject<PlayerConfig>()
|
||||||
|
private lateinit var playerActivity: Cache<String, String>
|
||||||
|
|
||||||
override fun enable() {
|
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("survival", "s"), GamemodeCommand(GameMode.SURVIVAL))
|
||||||
registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE))
|
registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE))
|
||||||
registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE))
|
registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE))
|
||||||
registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR))
|
registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR))
|
||||||
registerCommandExecutor(listOf("localweather", "lw"), LocalWeatherCommand())
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
10
foundation-core/src/main/resources/player.yaml
Normal file
10
foundation-core/src/main/resources/player.yaml
Normal 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: []
|
Reference in New Issue
Block a user