Tracks races played, wins, total laps, and best times per player and per race, recorded off the main thread after each finish. Backed by a StatsStorage interface with two implementations: the default YamlStatsStorage (stats.yml, zero setup) and MySqlStatsStorage (HikariCP-pooled, auto-creates its tables, configured via config.yml). MySQL init failures fall back to YAML rather than blocking plugin startup. Adds /boatparty stats and /boatparty top commands. Bundles and relocates HikariCP + MySQL Connector/J via shadow (bumped to 9.0.2, the prior 8.3.5 couldn't shade Java 25 class files). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d6f1f53681
commit
b56d4b064b
@@ -0,0 +1,75 @@
|
||||
package us.tss3.boatparty.stats;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class StatsManager {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
private StatsStorage storage;
|
||||
|
||||
public StatsManager(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.storage = buildStorage(plugin);
|
||||
}
|
||||
|
||||
private static StatsStorage buildStorage(JavaPlugin plugin) {
|
||||
FileConfiguration config = plugin.getConfig();
|
||||
String type = config.getString("storage.type", "yaml");
|
||||
|
||||
if ("mysql".equalsIgnoreCase(type)) {
|
||||
return new MySqlStatsStorage(
|
||||
config.getString("storage.mysql.host", "localhost"),
|
||||
config.getInt("storage.mysql.port", 3306),
|
||||
config.getString("storage.mysql.database", "boatparty"),
|
||||
config.getString("storage.mysql.username", "root"),
|
||||
config.getString("storage.mysql.password", ""),
|
||||
config.getBoolean("storage.mysql.use-ssl", false),
|
||||
config.getString("storage.mysql.table-prefix", "boatparty_"),
|
||||
plugin.getLogger());
|
||||
}
|
||||
return new YamlStatsStorage(plugin.getDataFolder(), plugin.getLogger());
|
||||
}
|
||||
|
||||
public void init() {
|
||||
try {
|
||||
storage.init();
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Failed to initialize " + storage.getClass().getSimpleName()
|
||||
+ ", falling back to YAML stats storage: " + e.getMessage());
|
||||
storage = new YamlStatsStorage(plugin.getDataFolder(), plugin.getLogger());
|
||||
try {
|
||||
storage.init();
|
||||
} catch (Exception fallbackError) {
|
||||
throw new IllegalStateException("Failed to initialize fallback YAML stats storage", fallbackError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
storage.close();
|
||||
}
|
||||
|
||||
public void recordFinishAsync(UUID uuid, String playerName, String raceName, int place, long timeMillis, int laps) {
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin,
|
||||
() -> storage.recordFinish(uuid, playerName, raceName, place, timeMillis, laps));
|
||||
}
|
||||
|
||||
public void getStatsAsync(UUID uuid, Consumer<PlayerStats> callback) {
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
PlayerStats stats = storage.getStats(uuid);
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> callback.accept(stats));
|
||||
});
|
||||
}
|
||||
|
||||
public void getTopTimesAsync(String raceName, int limit, Consumer<List<TopEntry>> callback) {
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
List<TopEntry> entries = storage.getTopTimes(raceName, limit);
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> callback.accept(entries));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user