From 8c637a7bcfee057c1b6cbc3ed5adda4d92581a69 Mon Sep 17 00:00:00 2001 From: froobynooby Date: Thu, 21 Mar 2024 18:59:41 +0930 Subject: [PATCH] Fix metrics on Folia servers --- build.gradle | 2 +- .../farmcontrol/metrics/FcMetrics.java | 1 - .../farmcontrol/metrics/Metrics.java | 129 ++++++++++++++++++ 3 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/froobworld/farmcontrol/metrics/Metrics.java diff --git a/build.gradle b/build.gradle index 2960f59..e335c6e 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { compileOnly 'me.clip:placeholderapi:2.10.9' implementation 'org.jooq:joor-java-8:0.9.14' implementation 'com.github.froobynooby:nab-configuration:master-SNAPSHOT' //'com.froobworld:nab-configuration:1.0.2' - implementation 'org.bstats:bstats-bukkit:3.0.2' + implementation 'org.bstats:bstats-base:3.0.2' } processResources { diff --git a/src/main/java/com/froobworld/farmcontrol/metrics/FcMetrics.java b/src/main/java/com/froobworld/farmcontrol/metrics/FcMetrics.java index 1177450..7fea018 100644 --- a/src/main/java/com/froobworld/farmcontrol/metrics/FcMetrics.java +++ b/src/main/java/com/froobworld/farmcontrol/metrics/FcMetrics.java @@ -2,7 +2,6 @@ import com.froobworld.farmcontrol.FarmControl; import com.froobworld.farmcontrol.metrics.charts.*; -import org.bstats.bukkit.Metrics; public class FcMetrics { private final FarmControl farmControl; diff --git a/src/main/java/com/froobworld/farmcontrol/metrics/Metrics.java b/src/main/java/com/froobworld/farmcontrol/metrics/Metrics.java new file mode 100644 index 0000000..3c55b46 --- /dev/null +++ b/src/main/java/com/froobworld/farmcontrol/metrics/Metrics.java @@ -0,0 +1,129 @@ +package com.froobworld.farmcontrol.metrics; + +import com.froobworld.farmcontrol.FarmControl; +import org.bstats.MetricsBase; +import org.bstats.charts.CustomChart; +import org.bstats.json.JsonObjectBuilder; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.UUID; +import java.util.logging.Level; + +public class Metrics { + private final FarmControl plugin; + private final MetricsBase metricsBase; + + /** + * Creates a new Metrics instance. + * + * @param plugin Your plugin instance. + * @param serviceId The id of the service. + * It can be found at What is my plugin id? + */ + public Metrics(FarmControl plugin, int serviceId) { + this.plugin = plugin; + + // Get the config file + File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); + File configFile = new File(bStatsFolder, "config.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + + if (!config.isSet("serverUuid")) { + config.addDefault("enabled", true); + config.addDefault("serverUuid", UUID.randomUUID().toString()); + config.addDefault("logFailedRequests", false); + config.addDefault("logSentData", false); + config.addDefault("logResponseStatusText", false); + + // Inform the server owners about bStats + config.options().header( + "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" + + "many people use their plugin and their total player count. It's recommended to keep bStats\n" + + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" + + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" + + "anonymous." + ).copyDefaults(true); + try { + config.save(configFile); + } catch (IOException ignored) { } + } + + // Load the data + boolean enabled = config.getBoolean("enabled", true); + String serverUUID = config.getString("serverUuid"); + boolean logErrors = config.getBoolean("logFailedRequests", false); + boolean logSentData = config.getBoolean("logSentData", false); + boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); + + metricsBase = new MetricsBase( + "bukkit", + serverUUID, + serviceId, + enabled, + this::appendPlatformData, + this::appendServiceData, + plugin.getHookManager().getSchedulerHook()::runTask, + plugin::isEnabled, + (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), + (message) -> this.plugin.getLogger().log(Level.INFO, message), + logErrors, + logSentData, + logResponseStatusText + ); + } + + /** + * Shuts down the underlying scheduler service. + */ + public void shutdown() { + metricsBase.shutdown(); + } + + /** + * Adds a custom chart. + * + * @param chart The chart to add. + */ + public void addCustomChart(CustomChart chart) { + metricsBase.addCustomChart(chart); + } + + private void appendPlatformData(JsonObjectBuilder builder) { + builder.appendField("playerAmount", getPlayerAmount()); + builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); + builder.appendField("bukkitVersion", Bukkit.getVersion()); + builder.appendField("bukkitName", Bukkit.getName()); + + builder.appendField("javaVersion", System.getProperty("java.version")); + builder.appendField("osName", System.getProperty("os.name")); + builder.appendField("osArch", System.getProperty("os.arch")); + builder.appendField("osVersion", System.getProperty("os.version")); + builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); + } + + private void appendServiceData(JsonObjectBuilder builder) { + builder.appendField("pluginVersion", plugin.getDescription().getVersion()); + } + + private int getPlayerAmount() { + try { + // Around MC 1.8 the return type was changed from an array to a collection, + // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; + Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); + return onlinePlayersMethod.getReturnType().equals(Collection.class) + ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() + : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; + } catch (Exception e) { + return Bukkit.getOnlinePlayers().size(); // Just use the new method if the reflection failed + } + } + +} \ No newline at end of file