Add persistent player stats and DB support

Introduce MySQL persistence and an in-memory stats system with async saving.

- Add HikariCP & MySQL connector dependencies and relocate libs in build.gradle.kts.
- Add DatabaseManager (HikariCP) to manage connection pool and lifecycle.
- Add PlayerStats data model and PlayerStatsRepository for table creation, reads, upserts and batch upserts (with prepared statements).
- Add StatsManager: coroutine-based cache, dirty-flags, async batch saves, auto-save (every 5 minutes), load/save APIs and shutdown save.
- Add StatsListener: load on AsyncPlayerPreLoginEvent and save on PlayerQuitEvent.
- Wire DB and stats into main plugin: connect on enable (disable plugin on fail), initialize StatsManager, save/disconnect on disable, register leaderboard command and stats listener.
- Update GameManager to record kills/wins/deaths and adjust scrimScore on events.
- Add LeaderboardCommand and language entries for leaderboard output; expose command in plugin.yml.
- Add database configuration section to config.yml.
- Minor refactor: KitCommand plugin accessor changed to a getter.

These changes provide a robust, pooled DB connection and efficient stats persistence (batched/upserted) to reduce DB load and ensure data safety during shutdown.
This commit is contained in:
TDSTOS
2026-03-26 00:10:26 +01:00
parent ee79dd4bf4
commit 2d720d962c
13 changed files with 818 additions and 11 deletions

View File

@@ -1,7 +1,10 @@
package club.mcscrims.speedhg
import club.mcscrims.speedhg.command.KitCommand
import club.mcscrims.speedhg.command.LeaderboardCommand
import club.mcscrims.speedhg.config.LanguageManager
import club.mcscrims.speedhg.database.DatabaseManager
import club.mcscrims.speedhg.database.StatsManager
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.game.modules.AntiRunningManager
import club.mcscrims.speedhg.kit.KitManager
@@ -13,6 +16,7 @@ import club.mcscrims.speedhg.kit.listener.KitEventDispatcher
import club.mcscrims.speedhg.listener.ConnectListener
import club.mcscrims.speedhg.listener.GameStateListener
import club.mcscrims.speedhg.listener.SoupListener
import club.mcscrims.speedhg.listener.StatsListener
import club.mcscrims.speedhg.scoreboard.ScoreboardManager
import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin
@@ -41,21 +45,37 @@ class SpeedHG : JavaPlugin() {
lateinit var kitManager: KitManager
private set
lateinit var databaseManager: DatabaseManager
private set
lateinit var statsManager: StatsManager
private set
override fun onEnable()
{
instance = this
saveDefaultConfig()
languageManager = LanguageManager( this )
gameManager = GameManager( this )
antiRunningManager = AntiRunningManager( this )
databaseManager = DatabaseManager( this )
try {
databaseManager.connect()
} catch ( e: Exception ) {
logger.severe( "[Database] Verbindung fehlgeschlagen: ${e.message}" )
logger.severe( "[Database] Plugin wird deaktiviert." )
server.pluginManager.disablePlugin( this )
return
}
scoreboardManager = ScoreboardManager( this )
statsManager = StatsManager( this )
statsManager.initialize()
languageManager = LanguageManager( this )
gameManager = GameManager( this )
antiRunningManager = AntiRunningManager( this )
scoreboardManager = ScoreboardManager( this )
kitManager = KitManager( this )
kitManager = KitManager( this )
registerKits()
registerCommands()
registerListener()
@@ -64,6 +84,8 @@ class SpeedHG : JavaPlugin() {
override fun onDisable()
{
if ( ::statsManager.isInitialized ) statsManager.shutdown()
if ( ::databaseManager.isInitialized ) databaseManager.disconnect()
kitManager.clearAll()
super.onDisable()
}
@@ -81,6 +103,8 @@ class SpeedHG : JavaPlugin() {
val kitCommand = KitCommand()
getCommand( "kit" )?.setExecutor( kitCommand )
getCommand( "kit" )?.tabCompleter = kitCommand
getCommand( "leaderboard" )?.setExecutor( LeaderboardCommand() )
}
private fun registerListener()
@@ -91,6 +115,7 @@ class SpeedHG : JavaPlugin() {
pm.registerEvents( GameStateListener(), this )
pm.registerEvents( SoupListener(), this )
pm.registerEvents(KitEventDispatcher( this, kitManager ), this )
pm.registerEvents( StatsListener(), this )
}
}