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 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> callback) { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { List entries = storage.getTopTimes(raceName, limit); plugin.getServer().getScheduler().runTask(plugin, () -> callback.accept(entries)); }); } }