mirror of
				https://github.com/GayPizzaSpecifications/foundation.git
				synced 2025-11-03 19:29:38 +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("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")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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