Heimdall: Player Session Tracking

This commit is contained in:
Kenneth Endfinger 2021-12-24 02:42:13 -05:00
parent 139249c1de
commit 1985b3c507
No known key found for this signature in database
GPG Key ID: C4E68E5647420E10
6 changed files with 91 additions and 13 deletions

View File

@ -7,20 +7,25 @@ import cloud.kubelet.foundation.heimdall.buffer.EventBuffer
import cloud.kubelet.foundation.heimdall.event.BlockBreak
import cloud.kubelet.foundation.heimdall.event.BlockPlace
import cloud.kubelet.foundation.heimdall.event.PlayerPosition
import cloud.kubelet.foundation.heimdall.event.PlayerSession
import cloud.kubelet.foundation.heimdall.model.HeimdallConfig
import com.charleskorn.kaml.Yaml
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.block.BlockPlaceEvent
import org.bukkit.event.entity.EntityDeathEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.plugin.java.JavaPlugin
import org.jetbrains.exposed.sql.Database
import org.postgresql.Driver
import java.lang.Exception
import java.time.Instant
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.io.path.inputStream
class FoundationHeimdallPlugin : JavaPlugin(), Listener {
@ -31,6 +36,8 @@ class FoundationHeimdallPlugin : JavaPlugin(), Listener {
private val buffer = EventBuffer()
private val bufferFlushThread = BufferFlushThread(this, buffer)
private val playerJoinTimes = ConcurrentHashMap<UUID, Instant>()
override fun onEnable() {
val foundation = server.pluginManager.getPlugin("Foundation") as FoundationCorePlugin
@ -91,7 +98,25 @@ class FoundationHeimdallPlugin : JavaPlugin(), Listener {
@EventHandler
fun onBlockBroken(event: BlockBreakEvent) = buffer.push(BlockBreak(event))
@EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) {
playerJoinTimes[event.player.uniqueId] = Instant.now()
}
@EventHandler(priority = EventPriority.HIGHEST)
fun onPlayerQuit(event: PlayerQuitEvent) {
val startTime = playerJoinTimes.remove(event.player.uniqueId) ?: return
val endTime = Instant.now()
buffer.push(PlayerSession(event.player.uniqueId, event.player.name, startTime, endTime))
}
override fun onDisable() {
bufferFlushThread.stop()
val endTime = Instant.now()
for (playerId in playerJoinTimes.keys().toList()) {
val startTime = playerJoinTimes.remove(playerId) ?: continue
buffer.push(PlayerSession(playerId, server.getPlayer(playerId)?.name ?: "__unknown__", startTime, endTime))
}
bufferFlushThread.flush()
}
}

View File

@ -6,12 +6,30 @@ import java.util.concurrent.atomic.AtomicBoolean
class BufferFlushThread(val plugin: FoundationHeimdallPlugin, val buffer: EventBuffer) {
private val running = AtomicBoolean(false)
private var thread: Thread? = null
fun start() {
running.set(true)
val thread = Thread {
plugin.slF4JLogger.info("Buffer Flusher Started")
while (running.get()) {
flush()
Thread.sleep(5000)
}
plugin.slF4JLogger.info("Buffer Flusher Stopped")
}
thread.name = "Heimdall Buffer Flush"
thread.isDaemon = false
thread.start()
this.thread = thread
}
fun stop() {
running.set(false)
thread?.join()
}
fun flush() {
try {
transaction(plugin.db) {
val count = buffer.flush(this)
@ -22,16 +40,5 @@ class BufferFlushThread(val plugin: FoundationHeimdallPlugin, val buffer: EventB
} catch (e: Exception) {
plugin.slF4JLogger.warn("Failed to flush buffer.", e)
}
Thread.sleep(5000)
}
plugin.slF4JLogger.info("Buffer Flusher Stopped")
}
thread.name = "Heimdall Buffer Flush"
thread.isDaemon = false
thread.start()
}
fun stop() {
running.set(false)
}
}

View File

@ -0,0 +1,25 @@
package cloud.kubelet.foundation.heimdall.event
import cloud.kubelet.foundation.heimdall.table.PlayerSessionTable
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.*
class PlayerSession(
val playerUniqueIdentity: UUID,
val playerName: String,
val startTimeInstant: Instant,
val endTimeInstant: Instant
) : HeimdallEvent() {
override fun store(transaction: Transaction) {
transaction.apply {
PlayerSessionTable.insert {
it[player] = playerUniqueIdentity
it[name] = playerName
it[startTime] = startTimeInstant
it[endTime] = endTimeInstant
}
}
}
}

View File

@ -0,0 +1,11 @@
package cloud.kubelet.foundation.heimdall.table
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.javatime.timestamp
object PlayerSessionTable : Table("player_sessions") {
val player = uuid("player")
val name = text("name")
val startTime = timestamp("start")
val endTime = timestamp("end")
}

View File

@ -44,3 +44,13 @@ create table if not exists heimdall.block_places (
);
--
select create_hypertable('heimdall.block_places', 'time', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.player_sessions (
player uuid not null,
name text not null,
"start" timestamp not null,
"end" timestamp not null,
PRIMARY KEY (player, start)
);
--
select create_hypertable('heimdall.player_sessions', 'start', 'player', 4, if_not_exists => TRUE);