mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-02 21:20:55 +00:00
Heimdall: Player Session Tracking
This commit is contained in:
parent
139249c1de
commit
1985b3c507
@ -7,20 +7,25 @@ import cloud.kubelet.foundation.heimdall.buffer.EventBuffer
|
|||||||
import cloud.kubelet.foundation.heimdall.event.BlockBreak
|
import cloud.kubelet.foundation.heimdall.event.BlockBreak
|
||||||
import cloud.kubelet.foundation.heimdall.event.BlockPlace
|
import cloud.kubelet.foundation.heimdall.event.BlockPlace
|
||||||
import cloud.kubelet.foundation.heimdall.event.PlayerPosition
|
import cloud.kubelet.foundation.heimdall.event.PlayerPosition
|
||||||
|
import cloud.kubelet.foundation.heimdall.event.PlayerSession
|
||||||
import cloud.kubelet.foundation.heimdall.model.HeimdallConfig
|
import cloud.kubelet.foundation.heimdall.model.HeimdallConfig
|
||||||
import com.charleskorn.kaml.Yaml
|
import com.charleskorn.kaml.Yaml
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.EventPriority
|
||||||
import org.bukkit.event.Listener
|
import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.block.BlockBreakEvent
|
import org.bukkit.event.block.BlockBreakEvent
|
||||||
import org.bukkit.event.block.BlockPlaceEvent
|
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.PlayerMoveEvent
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
import org.postgresql.Driver
|
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
|
import kotlin.io.path.inputStream
|
||||||
|
|
||||||
class FoundationHeimdallPlugin : JavaPlugin(), Listener {
|
class FoundationHeimdallPlugin : JavaPlugin(), Listener {
|
||||||
@ -31,6 +36,8 @@ class FoundationHeimdallPlugin : JavaPlugin(), Listener {
|
|||||||
private val buffer = EventBuffer()
|
private val buffer = EventBuffer()
|
||||||
private val bufferFlushThread = BufferFlushThread(this, buffer)
|
private val bufferFlushThread = BufferFlushThread(this, buffer)
|
||||||
|
|
||||||
|
private val playerJoinTimes = ConcurrentHashMap<UUID, Instant>()
|
||||||
|
|
||||||
override fun onEnable() {
|
override fun onEnable() {
|
||||||
val foundation = server.pluginManager.getPlugin("Foundation") as FoundationCorePlugin
|
val foundation = server.pluginManager.getPlugin("Foundation") as FoundationCorePlugin
|
||||||
|
|
||||||
@ -91,7 +98,25 @@ class FoundationHeimdallPlugin : JavaPlugin(), Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
fun onBlockBroken(event: BlockBreakEvent) = buffer.push(BlockBreak(event))
|
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() {
|
override fun onDisable() {
|
||||||
bufferFlushThread.stop()
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,14 @@ import java.util.concurrent.atomic.AtomicBoolean
|
|||||||
|
|
||||||
class BufferFlushThread(val plugin: FoundationHeimdallPlugin, val buffer: EventBuffer) {
|
class BufferFlushThread(val plugin: FoundationHeimdallPlugin, val buffer: EventBuffer) {
|
||||||
private val running = AtomicBoolean(false)
|
private val running = AtomicBoolean(false)
|
||||||
|
private var thread: Thread? = null
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
running.set(true)
|
running.set(true)
|
||||||
val thread = Thread {
|
val thread = Thread {
|
||||||
plugin.slF4JLogger.info("Buffer Flusher Started")
|
plugin.slF4JLogger.info("Buffer Flusher Started")
|
||||||
while (running.get()) {
|
while (running.get()) {
|
||||||
try {
|
flush()
|
||||||
transaction(plugin.db) {
|
|
||||||
val count = buffer.flush(this)
|
|
||||||
if (count > 0) {
|
|
||||||
plugin.slF4JLogger.info("Flushed $count Events")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
plugin.slF4JLogger.warn("Failed to flush buffer.", e)
|
|
||||||
}
|
|
||||||
Thread.sleep(5000)
|
Thread.sleep(5000)
|
||||||
}
|
}
|
||||||
plugin.slF4JLogger.info("Buffer Flusher Stopped")
|
plugin.slF4JLogger.info("Buffer Flusher Stopped")
|
||||||
@ -29,9 +21,24 @@ class BufferFlushThread(val plugin: FoundationHeimdallPlugin, val buffer: EventB
|
|||||||
thread.name = "Heimdall Buffer Flush"
|
thread.name = "Heimdall Buffer Flush"
|
||||||
thread.isDaemon = false
|
thread.isDaemon = false
|
||||||
thread.start()
|
thread.start()
|
||||||
|
this.thread = thread
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
running.set(false)
|
running.set(false)
|
||||||
|
thread?.join()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun flush() {
|
||||||
|
try {
|
||||||
|
transaction(plugin.db) {
|
||||||
|
val count = buffer.flush(this)
|
||||||
|
if (count > 0) {
|
||||||
|
plugin.slF4JLogger.info("Flushed $count Events")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
plugin.slF4JLogger.warn("Failed to flush buffer.", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ class BlockPlace(
|
|||||||
val location: Location,
|
val location: Location,
|
||||||
val material: Material,
|
val material: Material,
|
||||||
val timestamp: Instant = Instant.now()
|
val timestamp: Instant = Instant.now()
|
||||||
) : HeimdallEvent() {
|
) : HeimdallEvent() {
|
||||||
constructor(event: BlockPlaceEvent) : this(event.player.uniqueId, event.block.location, event.block.type)
|
constructor(event: BlockPlaceEvent) : this(event.player.uniqueId, event.block.location, event.block.type)
|
||||||
|
|
||||||
override fun store(transaction: Transaction) {
|
override fun store(transaction: Transaction) {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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")
|
||||||
|
}
|
@ -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);
|
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user