Skip to content

SLNE-Development/surf-stats

Repository files navigation

Surf Stats

A Paper plugin that reads Minecraft's per-player statistics JSON files and persists them to a MySQL/MariaDB database. Statistics are captured on player logout, periodic world saves, and server shutdown.

Modules

Module Description
surf-stats-api Public API interfaces and data models
surf-stats-core Core implementation (file parsing, database persistence)
surf-stats-paper Paper plugin (event listeners, lifecycle management)

Requirements

Building

./gradlew :surf-stats-paper:build

The plugin jar is produced at surf-stats-paper/build/libs/.

Configuration

config.yml

server:
  name: "my-server"      # Unique identifier for this server (must be changed)
  label: "My Server"     # Human-readable display name

The plugin will refuse to start if server.name is left as my-server.

database.yml

logLevel: DEBUG
credentials:
  host: localhost
  port: 3306
  database: my_database
  username: my_user
  password: my_password
pool:
  sizing:
    initialSize: 10
    minIdle: 0
    maxSize: 10
  timeouts:
    maxAcquireTimeMillis: 10000
    maxCreateConnectionTimeMillis: 30000
    maxValidationTimeMillis: -1
    maxIdleTimeMillis: 60000
    maxLifeTimeMillis: 1800000

How It Works

The plugin reads Minecraft's native <world>/stats/<uuid>.json files and writes the data to a relational database, attributing each entry to the configured server name.

Statistics are processed at three points:

  1. Player quit — 1 second after disconnect (gives Minecraft time to flush the stats file)
  2. World save — 5 seconds after a world save cycle completes (debounced across overworld/nether/end)
  3. Server shutdown — synchronously during plugin disable, ensuring all online players' stats are saved before the database connection closes

All async processing uses a shared plugin-scoped CoroutineScope that is cancelled on shutdown to prevent post-disable coroutine leaks.

API Usage

Other plugins can access the API through Bukkit's ServicesManager:

val api = server.servicesManager.getRegistration(SurfStatsApi::class.java)?.provider
    ?: error("SurfStats not available")

// Load a player's stats
val stats: PlayerStats? = api.getPlayerStats(playerUuid, playerName)

// Access individual stat values
val blocksMined = stats?.getStat("minecraft:mined", "minecraft:stone")

// Get all categories
val categories: Set<String> = stats?.categories() ?: emptySet()

Custom Stats

Other plugins can save custom statistics into the minecraft:custom category:

val api = server.servicesManager.getRegistration(SurfStatsApi::class.java)?.provider
    ?: error("SurfStats not available")

// Save a single custom stat
api.saveCustomStat(playerUuid, playerName, "my_plugin:kills", 42L)

// Save multiple custom stats at once (single transaction)
api.saveCustomStats(playerUuid, playerName, mapOf(
    "my_plugin:kills" to 42L,
    "my_plugin:deaths" to 7L
))

Both methods are suspend functions and must be called from a coroutine context. The database service must be available or an IllegalStateException is thrown.

Key API Types

  • SurfStatsApi — main entry point for reading and processing stats
  • PlayerStats — a player's full statistics (uuid, name, dataVersion, stat entries)
  • StatEntry — a single statistic: category (e.g. minecraft:mined), key (e.g. minecraft:stone), value
  • PlayerStatsBatch — a PlayerStats paired with a server name, ready for database insertion

Dependency (Gradle)

dependencies {
    compileOnly(project(":surf-stats-api"))
}

Database Schema

The plugin creates and manages these tables:

Table Purpose
servers Registered server names and labels
players Player UUIDs, names, data versions, timestamps
stat_categories Unique stat category names (e.g. minecraft:mined)
stat_keys Unique stat key names (e.g. minecraft:stone)
player_stats Stat values per player, per key, per server

License

SLNE Dev Team

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages