Remove heimdall and tool project.

This commit is contained in:
Liv Gorence
2023-01-26 20:36:48 -08:00
parent cf2a812b75
commit cec3b1297a
84 changed files with 3 additions and 2560 deletions

View File

@ -1,7 +0,0 @@
dependencies {
api("org.postgresql:postgresql:42.3.1")
api("org.jetbrains.exposed:exposed-jdbc:0.36.2")
api("org.jetbrains.exposed:exposed-java-time:0.36.2")
api("com.zaxxer:HikariCP:5.0.0")
compileOnly(project(":foundation-core"))
}

View File

@ -1,21 +0,0 @@
package gay.pizza.foundation.heimdall
fun String.sqlSplitStatements(): List<String> {
val statements = mutableListOf<String>()
val buffer = StringBuilder()
fun flush() {
val trimmed = buffer.toString().trim()
if (trimmed.isNotEmpty()) {
statements.add(trimmed)
}
}
for (line in lines()) {
if (line.trim() == "--") {
flush()
} else {
buffer.append(line).append("\n")
}
}
flush()
return statements
}

View File

@ -1,183 +0,0 @@
package gay.pizza.foundation.heimdall
import com.charleskorn.kaml.Yaml
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import gay.pizza.foundation.core.FoundationCorePlugin
import gay.pizza.foundation.core.Util
import gay.pizza.foundation.heimdall.buffer.BufferFlushThread
import gay.pizza.foundation.heimdall.buffer.EventBuffer
import gay.pizza.foundation.heimdall.event.BlockBreak
import gay.pizza.foundation.heimdall.event.BlockPlace
import gay.pizza.foundation.heimdall.event.EntityKill
import gay.pizza.foundation.heimdall.event.PlayerAdvancement
import gay.pizza.foundation.heimdall.event.PlayerDeath
import gay.pizza.foundation.heimdall.event.PlayerPosition
import gay.pizza.foundation.heimdall.event.PlayerSession
import gay.pizza.foundation.heimdall.event.WorldChange
import gay.pizza.foundation.heimdall.export.ExportChunksCommand
import gay.pizza.foundation.heimdall.model.HeimdallConfig
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.event.EventHandler
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.entity.PlayerDeathEvent
import org.bukkit.event.player.PlayerAdvancementDoneEvent
import org.bukkit.event.player.PlayerChangedWorldEvent
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.time.Duration
import java.time.Instant
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import kotlin.io.path.inputStream
class FoundationHeimdallPlugin : JavaPlugin(), Listener {
private lateinit var config: HeimdallConfig
private lateinit var pool: HikariDataSource
internal var db: Database? = null
private val buffer = EventBuffer()
private val bufferFlushThread = BufferFlushThread(this, buffer)
private val playerJoinTimes = ConcurrentHashMap<UUID, Instant>()
private val legacyComponentSerializer = LegacyComponentSerializer.builder().build()
override fun onEnable() {
val exportChunksCommand = getCommand("export_all_chunks") ?: throw Exception("Failed to get export_all_chunks command")
exportChunksCommand.setExecutor(ExportChunksCommand(this))
val foundation = server.pluginManager.getPlugin("Foundation") as FoundationCorePlugin
val configPath = Util.copyDefaultConfig<FoundationHeimdallPlugin>(
slF4JLogger,
foundation.pluginDataPath,
"heimdall.yaml"
)
config = Yaml.default.decodeFromStream(HeimdallConfig.serializer(), configPath.inputStream())
if (!config.enabled) {
slF4JLogger.info("Heimdall is not enabled.")
return
}
slF4JLogger.info("Heimdall is enabled.")
if (!Driver.isRegistered()) {
Driver.register()
}
pool = HikariDataSource(HikariConfig().apply {
jdbcUrl = config.db.url
username = config.db.username
password = config.db.password
schema = "heimdall"
maximumPoolSize = 10
idleTimeout = Duration.ofMinutes(5).toMillis()
maxLifetime = Duration.ofMinutes(10).toMillis()
})
val initMigrationContent = FoundationHeimdallPlugin::class.java.getResourceAsStream(
"/init.sql"
)?.readAllBytes()?.decodeToString() ?: throw RuntimeException("Unable to find Heimdall init.sql")
val statements = initMigrationContent.sqlSplitStatements()
pool.connection.use { conn ->
conn.autoCommit = false
try {
for (statementAsString in statements) {
conn.prepareStatement(statementAsString).use {
it.execute()
}
}
conn.commit()
} catch (e: Exception) {
conn.rollback()
throw e
} finally {
conn.autoCommit = true
}
}
db = Database.connect(pool)
server.pluginManager.registerEvents(this, this)
bufferFlushThread.start()
}
@EventHandler
fun onPlayerMove(event: PlayerMoveEvent) = buffer.push(PlayerPosition(event))
@EventHandler
fun onBlockBroken(event: BlockPlaceEvent) = buffer.push(BlockPlace(event))
@EventHandler
fun onBlockBroken(event: BlockBreakEvent) = buffer.push(BlockBreak(event))
@EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) {
playerJoinTimes[event.player.uniqueId] = Instant.now()
}
@EventHandler
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))
}
@EventHandler
fun onPlayerDeath(event: PlayerDeathEvent) {
val deathMessage = event.deathMessage()
val deathMessageString = if (deathMessage != null) {
legacyComponentSerializer.serialize(deathMessage)
} else {
null
}
buffer.push(PlayerDeath(event, deathMessageString))
}
@EventHandler
fun onPlayerAdvancementDone(event: PlayerAdvancementDoneEvent) = buffer.push(PlayerAdvancement(event))
@EventHandler
fun onWorldLoad(event: PlayerChangedWorldEvent) = buffer.push(
WorldChange(
event.player.uniqueId,
event.from.uid,
event.from.name,
event.player.world.uid,
event.player.world.name
)
)
@EventHandler
fun onEntityDeath(event: EntityDeathEvent) {
val killer = event.entity.killer ?: return
buffer.push(
EntityKill(
killer.uniqueId,
killer.location,
event.entity.uniqueId,
event.entityType.key.toString()
)
)
}
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

@ -1,49 +0,0 @@
package gay.pizza.foundation.heimdall.buffer
import gay.pizza.foundation.heimdall.FoundationHeimdallPlugin
import org.jetbrains.exposed.sql.transactions.transaction
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 {
val db = plugin.db
if (db == null) {
buffer.clear()
return
}
transaction(plugin.db) {
val count = buffer.flush(this)
if (count > 0) {
plugin.slF4JLogger.debug("Flushed $count Events")
}
}
} catch (e: Exception) {
plugin.slF4JLogger.warn("Failed to flush buffer.", e)
}
}
}

View File

@ -1,28 +0,0 @@
package gay.pizza.foundation.heimdall.buffer
import gay.pizza.foundation.heimdall.event.HeimdallEvent
import org.jetbrains.exposed.sql.Transaction
class EventBuffer {
private var events = mutableListOf<HeimdallEvent>()
fun flush(transaction: Transaction): Long {
val referenceOfEvents = events
this.events = mutableListOf()
var count = 0L
while (referenceOfEvents.isNotEmpty()) {
val event = referenceOfEvents.removeAt(0)
event.store(transaction)
count++
}
return count
}
fun push(event: HeimdallEvent) {
events.add(event)
}
fun clear() {
events = mutableListOf()
}
}

View File

@ -1,35 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.BlockBreakTable
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.event.block.BlockBreakEvent
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class BlockBreak(
val playerUniqueIdentity: UUID,
val location: Location,
val material: Material,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: BlockBreakEvent) : this(event.player.uniqueId, event.block.location, event.block.type)
override fun store(transaction: Transaction) {
transaction.apply {
BlockBreakTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[world] = location.world.uid
it[x] = location.x
it[y] = location.y
it[z] = location.z
it[pitch] = location.pitch.toDouble()
it[yaw] = location.yaw.toDouble()
it[block] = material.key.toString()
}
}
}
}

View File

@ -1,35 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.BlockPlaceTable
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.event.block.BlockPlaceEvent
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class BlockPlace(
val playerUniqueIdentity: UUID,
val location: Location,
val material: Material,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: BlockPlaceEvent) : this(event.player.uniqueId, event.block.location, event.block.type)
override fun store(transaction: Transaction) {
transaction.apply {
BlockPlaceTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[world] = location.world.uid
it[x] = location.x
it[y] = location.y
it[z] = location.z
it[pitch] = location.pitch.toDouble()
it[yaw] = location.yaw.toDouble()
it[block] = material.key.toString()
}
}
}
}

View File

@ -1,33 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.EntityKillTable
import org.bukkit.Location
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class EntityKill(
val playerUniqueIdentity: UUID,
val location: Location,
val entityUniqueIdentity: UUID,
val entityTypeName: String,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
override fun store(transaction: Transaction) {
transaction.apply {
EntityKillTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[world] = location.world.uid
it[x] = location.x
it[y] = location.y
it[z] = location.z
it[pitch] = location.pitch.toDouble()
it[yaw] = location.yaw.toDouble()
it[entity] = entityUniqueIdentity
it[entityType] = entityTypeName
}
}
}
}

View File

@ -1,7 +0,0 @@
package gay.pizza.foundation.heimdall.event
import org.jetbrains.exposed.sql.Transaction
abstract class HeimdallEvent {
abstract fun store(transaction: Transaction)
}

View File

@ -1,35 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.PlayerAdvancementTable
import org.bukkit.Location
import org.bukkit.advancement.Advancement
import org.bukkit.event.player.PlayerAdvancementDoneEvent
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class PlayerAdvancement(
val playerUniqueIdentity: UUID,
val location: Location,
val advancement: Advancement,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: PlayerAdvancementDoneEvent) : this(event.player.uniqueId, event.player.location, event.advancement)
override fun store(transaction: Transaction) {
transaction.apply {
PlayerAdvancementTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[world] = location.world.uid
it[x] = location.x
it[y] = location.y
it[z] = location.z
it[pitch] = location.pitch.toDouble()
it[yaw] = location.yaw.toDouble()
it[advancement] = this@PlayerAdvancement.advancement.key.toString()
}
}
}
}

View File

@ -1,41 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.PlayerDeathTable
import org.bukkit.Location
import org.bukkit.event.entity.PlayerDeathEvent
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class PlayerDeath(
val playerUniqueIdentity: UUID,
val location: Location,
val experienceLevel: Float,
val deathMessage: String?,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: PlayerDeathEvent, deathMessage: String? = null) : this(
event.player.uniqueId,
event.player.location,
event.player.exp,
deathMessage
)
override fun store(transaction: Transaction) {
transaction.apply {
PlayerDeathTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[world] = location.world.uid
it[x] = location.x
it[y] = location.y
it[z] = location.z
it[pitch] = location.pitch.toDouble()
it[yaw] = location.yaw.toDouble()
it[experience] = experienceLevel.toDouble()
it[message] = deathMessage
}
}
}
}

View File

@ -1,32 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.PlayerPositionTable
import org.bukkit.Location
import org.bukkit.event.player.PlayerMoveEvent
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class PlayerPosition(
val playerUniqueIdentity: UUID,
val location: Location,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: PlayerMoveEvent) : this(event.player.uniqueId, event.to)
override fun store(transaction: Transaction) {
transaction.apply {
PlayerPositionTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[world] = location.world.uid
it[x] = location.x
it[y] = location.y
it[z] = location.z
it[pitch] = location.pitch.toDouble()
it[yaw] = location.yaw.toDouble()
}
}
}
}

View File

@ -1,26 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.PlayerSessionTable
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
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[id] = UUID.randomUUID()
it[player] = playerUniqueIdentity
it[name] = playerName
it[startTime] = startTimeInstant
it[endTime] = endTimeInstant
}
}
}
}

View File

@ -1,29 +0,0 @@
package gay.pizza.foundation.heimdall.event
import gay.pizza.foundation.heimdall.table.WorldChangeTable
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.insert
import java.time.Instant
import java.util.UUID
class WorldChange(
val playerUniqueIdentity: UUID,
val fromWorldId: UUID,
val fromWorldActualName: String,
val toWorldId: UUID,
val toWorldActualName: String,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
override fun store(transaction: Transaction) {
transaction.apply {
WorldChangeTable.insert {
it[time] = timestamp
it[player] = playerUniqueIdentity
it[fromWorld] = fromWorldId
it[fromWorldName] = fromWorldActualName
it[toWorld] = toWorldId
it[toWorldName] = toWorldActualName
}
}
}
}

View File

@ -1,68 +0,0 @@
package gay.pizza.foundation.heimdall.export
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToStream
import org.bukkit.Chunk
import org.bukkit.ChunkSnapshot
import org.bukkit.Server
import org.bukkit.World
import org.bukkit.plugin.Plugin
import java.io.File
import java.util.zip.GZIPOutputStream
class ChunkExporter(private val plugin: Plugin, private val server: Server, val world: World) {
private val json = Json {
ignoreUnknownKeys = true
}
fun exportLoadedChunksAsync() {
exportChunkListAsync(world.loadedChunks.toList())
}
private fun exportChunkListAsync(chunks: List<Chunk>) {
plugin.slF4JLogger.info("Exporting ${chunks.size} Chunks")
val snapshots = chunks.map { it.chunkSnapshot }
Thread {
for (snapshot in snapshots) {
exportChunkSnapshot(snapshot)
}
plugin.slF4JLogger.info("Exported ${chunks.size} Chunks")
}.start()
}
private fun exportChunkSnapshot(snapshot: ChunkSnapshot) {
val sections = mutableListOf<ExportedChunkSection>()
val yRange = world.minHeight until world.maxHeight
val chunkRange = 0..15
for (x in chunkRange) {
for (z in chunkRange) {
sections.add(exportChunkSection(snapshot, yRange, x, z))
}
}
val exported = ExportedChunk(snapshot.x, snapshot.z, sections)
saveChunkSnapshot(snapshot, exported)
}
private fun saveChunkSnapshot(snapshot: ChunkSnapshot, chunk: ExportedChunk) {
val file = File("exported_chunks/${snapshot.worldName}_chunk_${snapshot.x}_${snapshot.z}.json.gz")
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
}
val fileOutputStream = file.outputStream()
val gzipOutputStream = GZIPOutputStream(fileOutputStream)
json.encodeToStream(ExportedChunk.serializer(), chunk, gzipOutputStream)
gzipOutputStream.close()
}
private fun exportChunkSection(snapshot: ChunkSnapshot, yRange: IntRange, x: Int, z: Int): ExportedChunkSection {
val blocks = mutableListOf<ExportedBlock>()
for (y in yRange) {
val blockData = snapshot.getBlockData(x, y, z)
val block = ExportedBlock(blockData.material.key.toString())
blocks.add(block)
}
return ExportedChunkSection(x, z, blocks)
}
}

View File

@ -1,17 +0,0 @@
package gay.pizza.foundation.heimdall.export
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.plugin.Plugin
class ExportChunksCommand(private val plugin: Plugin) : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
plugin.slF4JLogger.info("Exporting All Chunks")
for (world in sender.server.worlds) {
val export = ChunkExporter(plugin, sender.server, world)
export.exportLoadedChunksAsync()
}
return true
}
}

View File

@ -1,8 +0,0 @@
package gay.pizza.foundation.heimdall.export
import kotlinx.serialization.Serializable
@Serializable
data class ExportedBlock(
val type: String
)

View File

@ -1,10 +0,0 @@
package gay.pizza.foundation.heimdall.export
import kotlinx.serialization.Serializable
@Serializable
data class ExportedChunk(
val x: Int,
val z: Int,
val sections: List<ExportedChunkSection>
)

View File

@ -1,10 +0,0 @@
package gay.pizza.foundation.heimdall.export
import kotlinx.serialization.Serializable
@Serializable
data class ExportedChunkSection(
val x: Int,
val z: Int,
val blocks: List<ExportedBlock>
)

View File

@ -1,16 +0,0 @@
package gay.pizza.foundation.heimdall.model
import kotlinx.serialization.Serializable
@Serializable
data class HeimdallConfig(
val enabled: Boolean = false,
val db: DbConfig
)
@Serializable
data class DbConfig(
val url: String,
val username: String,
val password: String
)

View File

@ -1,16 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object BlockBreakTable : Table("block_breaks") {
val time = timestamp("time")
val player = uuid("player")
val world = uuid("world")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
val block = text("block")
}

View File

@ -1,16 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object BlockPlaceTable : Table("block_places") {
val time = timestamp("time")
val player = uuid("player")
val world = uuid("world")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
val block = text("block")
}

View File

@ -1,17 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object EntityKillTable : Table("entity_kills") {
val time = timestamp("time")
val player = uuid("player")
val entity = uuid("entity")
val world = uuid("world")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
val entityType = text("entity_type")
}

View File

@ -1,16 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object PlayerAdvancementTable : Table("player_advancements") {
val time = timestamp("time")
val player = uuid("player")
val world = uuid("world")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
val advancement = text("advancement")
}

View File

@ -1,17 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object PlayerDeathTable : Table("player_deaths") {
val time = timestamp("time")
val world = uuid("world")
val player = uuid("player")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
val experience = double("experience")
val message = text("message").nullable()
}

View File

@ -1,15 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object PlayerPositionTable : Table("player_positions") {
val time = timestamp("time")
val player = uuid("player")
val world = uuid("world")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
}

View File

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

View File

@ -1,13 +0,0 @@
package gay.pizza.foundation.heimdall.table
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object WorldChangeTable : Table("world_changes") {
val time = timestamp("time")
val player = uuid("player")
val fromWorld = uuid("from_world")
val toWorld = uuid("to_world")
val fromWorldName = text("from_world_name")
val toWorldName = text("to_world_name")
}

View File

@ -1,17 +0,0 @@
package gay.pizza.foundation.heimdall.view
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.javatime.timestamp
object BlockChangeView : Table("block_changes") {
val isBreak = bool("break")
val time = timestamp("time")
val player = uuid("player")
val world = uuid("world")
val x = double("x")
val y = double("y")
val z = double("z")
val pitch = double("pitch")
val yaw = double("yaw")
val block = text("block")
}

View File

@ -1,11 +0,0 @@
# Whether Heimdall should be enabled for tracking events.
enabled: false
# Database connection information.
db:
# JDBC URL
url: "jdbc:postgresql://localhost/foundation"
# JDBC Username
username: "foundation"
# JDBC Password
password: "foundation"

View File

@ -1,147 +0,0 @@
create extension if not exists "uuid-ossp";
--
create extension if not exists timescaledb;
--
create schema if not exists heimdall;
--
create table if not exists heimdall.player_positions (
time timestamp not null,
player uuid not null,
world uuid not null,
x double precision not null,
y double precision not null,
z double precision not null,
pitch double precision not null,
yaw double precision not null,
PRIMARY KEY (time, player, world)
);
--
select create_hypertable('heimdall.player_positions', 'time', 'player', 4, if_not_exists => TRUE);
--
alter table heimdall.player_positions set (
timescaledb.compress,
timescaledb.compress_segmentby = 'player,world',
timescaledb.compress_orderby = 'time'
);
--
select add_compression_policy('heimdall.player_positions', interval '3 days', if_not_exists => true);
--
create table if not exists heimdall.block_breaks (
time timestamp not null,
player uuid not null,
world uuid not null,
x double precision not null,
y double precision not null,
z double precision not null,
pitch double precision not null,
yaw double precision not null,
block text not null,
PRIMARY KEY (time, player, world)
);
--
select create_hypertable('heimdall.block_breaks', 'time', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.block_places (
time timestamp not null,
player uuid not null,
world uuid not null,
x double precision not null,
y double precision not null,
z double precision not null,
pitch double precision not null,
yaw double precision not null,
block text not null,
PRIMARY KEY (time, player, world)
);
--
select create_hypertable('heimdall.block_places', 'time', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.player_sessions (
id uuid not null,
player uuid not null,
name text not null,
"start" timestamp not null,
"end" timestamp not null,
primary key (id, player, start)
);
--
select create_hypertable('heimdall.player_sessions', 'start', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.world_changes (
time timestamp not null,
player uuid not null,
from_world uuid not null,
from_world_name text not null,
to_world uuid not null,
to_world_name text not null,
primary key (time, player)
);
--
select create_hypertable('heimdall.world_changes', 'time', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.player_deaths (
time timestamp not null,
player uuid not null,
world uuid not null,
x double precision not null,
y double precision not null,
z double precision not null,
pitch double precision not null,
yaw double precision not null,
experience double precision not null,
message text null,
primary key (time, player)
);
--
select create_hypertable('heimdall.player_deaths', 'time', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.player_advancements (
time timestamp not null,
player uuid not null,
world uuid not null,
x double precision not null,
y double precision not null,
z double precision not null,
pitch double precision not null,
yaw double precision not null,
advancement text not null,
primary key (time, player, advancement)
);
--
select create_hypertable('heimdall.player_advancements', 'time', 'player', 4, if_not_exists => TRUE);
--
create table if not exists heimdall.entity_kills (
time timestamp not null,
player uuid not null,
entity uuid not null,
world uuid not null,
x double precision not null,
y double precision not null,
z double precision not null,
pitch double precision not null,
yaw double precision not null,
entity_type text not null,
primary key (time, entity, player)
);
--
select create_hypertable('heimdall.entity_kills', 'time', 'player', 4, if_not_exists => TRUE);
--
create or replace view heimdall.block_changes as
select true as break, *
from heimdall.block_breaks
union all
select false as break, * from heimdall.block_places;
--
create or replace view heimdall.player_names as
with unique_player_ids as (
select distinct player
from heimdall.player_sessions
)
select player, (
select name
from heimdall.player_sessions
where player = unique_player_ids.player
order by "end" desc
limit 1
) as name
from unique_player_ids;

View File

@ -1,15 +0,0 @@
name: Foundation-Heimdall
version: '${version}'
main: gay.pizza.foundation.heimdall.FoundationHeimdallPlugin
api-version: 1.18
prefix: Foundation-Heimdall
load: STARTUP
depend:
- Foundation
authors:
- kubelet
commands:
export_all_chunks:
description: Export All Chunks
usage: /export_all_chunks
permission: foundation.heimdall.command.export_all_chunks