|
@@ -1,668 +1,82 @@
|
|
|
package de.Linus122.TimeIsMoney;
|
|
|
|
|
|
-import org.bukkit.Bukkit;
|
|
|
-import org.bukkit.configuration.file.YamlConfiguration;
|
|
|
-import org.bukkit.entity.Player;
|
|
|
-import org.bukkit.plugin.RegisteredServiceProvider;
|
|
|
-import org.bukkit.plugin.ServicePriority;
|
|
|
-import org.bukkit.plugin.java.JavaPlugin;
|
|
|
-import org.json.simple.JSONArray;
|
|
|
-import org.json.simple.JSONObject;
|
|
|
-
|
|
|
-import javax.net.ssl.HttpsURLConnection;
|
|
|
-import java.io.ByteArrayOutputStream;
|
|
|
import java.io.DataOutputStream;
|
|
|
-import java.io.File;
|
|
|
-import java.io.IOException;
|
|
|
-import java.lang.reflect.InvocationTargetException;
|
|
|
-import java.lang.reflect.Method;
|
|
|
-import java.net.URL;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Collection;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Timer;
|
|
|
-import java.util.TimerTask;
|
|
|
-import java.util.UUID;
|
|
|
-import java.util.concurrent.Callable;
|
|
|
-import java.util.logging.Level;
|
|
|
-import java.util.zip.GZIPOutputStream;
|
|
|
-
|
|
|
-
|
|
|
- * bStats collects some data for plugin authors.
|
|
|
- *
|
|
|
- * Check out https:
|
|
|
- * @link https:
|
|
|
- */
|
|
|
-public class Metrics {
|
|
|
-
|
|
|
- static {
|
|
|
-
|
|
|
- if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
|
|
|
-
|
|
|
- final String defaultPackage = new String(
|
|
|
- new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
|
|
|
- final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
|
|
-
|
|
|
- if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
|
|
|
- throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public static final int B_STATS_VERSION = 1;
|
|
|
-
|
|
|
-
|
|
|
- private static final String URL = "https://bStats.org/submitData/bukkit";
|
|
|
-
|
|
|
-
|
|
|
- private static boolean logFailedRequests;
|
|
|
-
|
|
|
-
|
|
|
- private static String serverUUID;
|
|
|
-
|
|
|
-
|
|
|
- private final JavaPlugin plugin;
|
|
|
-
|
|
|
-
|
|
|
- private final List<CustomChart> charts = new ArrayList<>();
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param plugin The plugin which stats should be submitted.
|
|
|
- */
|
|
|
- public Metrics(JavaPlugin plugin) {
|
|
|
- if (plugin == null) {
|
|
|
- throw new IllegalArgumentException("Plugin cannot be null!");
|
|
|
- }
|
|
|
- this.plugin = plugin;
|
|
|
-
|
|
|
-
|
|
|
- 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.options().header(
|
|
|
- "bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
|
|
|
- "To honor their work, you should not disable it.\n" +
|
|
|
- "This has nearly no effect on the server performance!\n" +
|
|
|
- "Check out https://bStats.org/ to learn more :)"
|
|
|
- ).copyDefaults(true);
|
|
|
- try {
|
|
|
- config.save(configFile);
|
|
|
- } catch (IOException ignored) { }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- serverUUID = config.getString("serverUuid");
|
|
|
- logFailedRequests = config.getBoolean("logFailedRequests", false);
|
|
|
- if (config.getBoolean("enabled", true)) {
|
|
|
- boolean found = false;
|
|
|
-
|
|
|
- for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
|
|
- try {
|
|
|
- service.getField("B_STATS_VERSION");
|
|
|
- found = true;
|
|
|
- break;
|
|
|
- } catch (NoSuchFieldException ignored) { }
|
|
|
- }
|
|
|
-
|
|
|
- Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
|
|
|
- if (!found) {
|
|
|
-
|
|
|
- startSubmitting();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Adds a custom chart.
|
|
|
- *
|
|
|
- * @param chart The chart to add.
|
|
|
- */
|
|
|
- public void addCustomChart(CustomChart chart) {
|
|
|
- if (chart == null) {
|
|
|
- throw new IllegalArgumentException("Chart cannot be null!");
|
|
|
- }
|
|
|
- charts.add(chart);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Starts the Scheduler which submits our data every 30 minutes.
|
|
|
- */
|
|
|
- private void startSubmitting() {
|
|
|
- final Timer timer = new Timer(true);
|
|
|
- timer.scheduleAtFixedRate(new TimerTask() {
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
- if (!plugin.isEnabled()) {
|
|
|
- timer.cancel();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
- submitData();
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }, 1000*60*5, 1000*60*30);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Gets the plugin specific data.
|
|
|
- * This method is called using Reflection.
|
|
|
- *
|
|
|
- * @return The plugin specific data.
|
|
|
- */
|
|
|
- public JSONObject getPluginData() {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
-
|
|
|
- String pluginName = plugin.getDescription().getName();
|
|
|
- String pluginVersion = plugin.getDescription().getVersion();
|
|
|
-
|
|
|
- data.put("pluginName", pluginName);
|
|
|
- data.put("pluginVersion", pluginVersion);
|
|
|
- JSONArray customCharts = new JSONArray();
|
|
|
- for (CustomChart customChart : charts) {
|
|
|
-
|
|
|
- JSONObject chart = customChart.getRequestJsonObject();
|
|
|
- if (chart == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- customCharts.add(chart);
|
|
|
- }
|
|
|
- data.put("customCharts", customCharts);
|
|
|
-
|
|
|
- return data;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Gets the server specific data.
|
|
|
- *
|
|
|
- * @return The server specific data.
|
|
|
- */
|
|
|
- private JSONObject getServerData() {
|
|
|
-
|
|
|
- int playerAmount;
|
|
|
- try {
|
|
|
-
|
|
|
-
|
|
|
- Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
|
|
|
- playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
|
|
|
- ? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
|
|
|
- : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
|
|
|
- } catch (Exception e) {
|
|
|
- playerAmount = Bukkit.getOnlinePlayers().size();
|
|
|
- }
|
|
|
- int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
|
|
|
- String bukkitVersion = org.bukkit.Bukkit.getVersion();
|
|
|
- bukkitVersion = bukkitVersion.substring(bukkitVersion.indexOf("MC: ") + 4, bukkitVersion.length() - 1);
|
|
|
-
|
|
|
-
|
|
|
- String javaVersion = System.getProperty("java.version");
|
|
|
- String osName = System.getProperty("os.name");
|
|
|
- String osArch = System.getProperty("os.arch");
|
|
|
- String osVersion = System.getProperty("os.version");
|
|
|
- int coreCount = Runtime.getRuntime().availableProcessors();
|
|
|
-
|
|
|
- JSONObject data = new JSONObject();
|
|
|
-
|
|
|
- data.put("serverUUID", serverUUID);
|
|
|
-
|
|
|
- data.put("playerAmount", playerAmount);
|
|
|
- data.put("onlineMode", onlineMode);
|
|
|
- data.put("bukkitVersion", bukkitVersion);
|
|
|
-
|
|
|
- data.put("javaVersion", javaVersion);
|
|
|
- data.put("osName", osName);
|
|
|
- data.put("osArch", osArch);
|
|
|
- data.put("osVersion", osVersion);
|
|
|
- data.put("coreCount", coreCount);
|
|
|
-
|
|
|
- return data;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Collects the data and sends it afterwards.
|
|
|
- */
|
|
|
- private void submitData() {
|
|
|
- final JSONObject data = getServerData();
|
|
|
-
|
|
|
- JSONArray pluginData = new JSONArray();
|
|
|
-
|
|
|
- for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
|
|
- try {
|
|
|
- service.getField("B_STATS_VERSION");
|
|
|
-
|
|
|
- for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
|
|
|
- try {
|
|
|
- pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
|
|
|
- } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
|
|
|
- }
|
|
|
- } catch (NoSuchFieldException ignored) { }
|
|
|
- }
|
|
|
-
|
|
|
- data.put("plugins", pluginData);
|
|
|
-
|
|
|
-
|
|
|
- new Thread(new Runnable() {
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
- try {
|
|
|
-
|
|
|
- sendData(data);
|
|
|
- } catch (Exception e) {
|
|
|
-
|
|
|
- if (logFailedRequests) {
|
|
|
- plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }).start();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Sends the data to the bStats server.
|
|
|
- *
|
|
|
- * @param data The data to send.
|
|
|
- * @throws Exception If the request failed.
|
|
|
- */
|
|
|
- private static void sendData(JSONObject data) throws Exception {
|
|
|
- if (data == null) {
|
|
|
- throw new IllegalArgumentException("Data cannot be null!");
|
|
|
- }
|
|
|
- if (Bukkit.isPrimaryThread()) {
|
|
|
- throw new IllegalAccessException("This method must not be called from the main thread!");
|
|
|
- }
|
|
|
- HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
|
|
|
-
|
|
|
-
|
|
|
- byte[] compressedData = compress(data.toString());
|
|
|
-
|
|
|
-
|
|
|
- connection.setRequestMethod("POST");
|
|
|
- connection.addRequestProperty("Accept", "application/json");
|
|
|
- connection.addRequestProperty("Connection", "close");
|
|
|
- connection.addRequestProperty("Content-Encoding", "gzip");
|
|
|
- connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
|
|
- connection.setRequestProperty("Content-Type", "application/json");
|
|
|
- connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
|
|
|
-
|
|
|
-
|
|
|
- connection.setDoOutput(true);
|
|
|
- DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
|
|
|
- outputStream.write(compressedData);
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.util.HashMap;
|
|
|
|
|
|
- connection.getInputStream().close();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Gzips the given String.
|
|
|
- *
|
|
|
- * @param str The string to gzip.
|
|
|
- * @return The gzipped String.
|
|
|
- * @throws IOException If the compression failed.
|
|
|
- */
|
|
|
- private static byte[] compress(final String str) throws IOException {
|
|
|
- if (str == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
- GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
|
|
- gzip.write(str.getBytes("UTF-8"));
|
|
|
- gzip.close();
|
|
|
- return outputStream.toByteArray();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom chart.
|
|
|
- */
|
|
|
- public static abstract class CustomChart {
|
|
|
-
|
|
|
-
|
|
|
- final String chartId;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- */
|
|
|
- CustomChart(String chartId) {
|
|
|
- if (chartId == null || chartId.isEmpty()) {
|
|
|
- throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
|
|
- }
|
|
|
- this.chartId = chartId;
|
|
|
- }
|
|
|
-
|
|
|
- private JSONObject getRequestJsonObject() {
|
|
|
- JSONObject chart = new JSONObject();
|
|
|
- chart.put("chartId", chartId);
|
|
|
- try {
|
|
|
- JSONObject data = getChartData();
|
|
|
- if (data == null) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- chart.put("data", data);
|
|
|
- } catch (Throwable t) {
|
|
|
- if (logFailedRequests) {
|
|
|
- Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
- return chart;
|
|
|
- }
|
|
|
-
|
|
|
- protected abstract JSONObject getChartData() throws Exception;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom simple pie.
|
|
|
- */
|
|
|
- public static class SimplePie extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<String> callable;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public SimplePie(String chartId, Callable<String> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- String value = callable.call();
|
|
|
- if (value == null || value.isEmpty()) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- data.put("value", value);
|
|
|
- return data;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom advanced pie.
|
|
|
- */
|
|
|
- public static class AdvancedPie extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<Map<String, Integer>> callable;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- JSONObject values = new JSONObject();
|
|
|
- Map<String, Integer> map = callable.call();
|
|
|
- if (map == null || map.isEmpty()) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- boolean allSkipped = true;
|
|
|
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
|
|
- if (entry.getValue() == 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- allSkipped = false;
|
|
|
- values.put(entry.getKey(), entry.getValue());
|
|
|
- }
|
|
|
- if (allSkipped) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- data.put("values", values);
|
|
|
- return data;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom drilldown pie.
|
|
|
- */
|
|
|
- public static class DrilldownPie extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<Map<String, Map<String, Integer>>> callable;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- JSONObject values = new JSONObject();
|
|
|
- Map<String, Map<String, Integer>> map = callable.call();
|
|
|
- if (map == null || map.isEmpty()) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- boolean reallyAllSkipped = true;
|
|
|
- for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
|
|
|
- JSONObject value = new JSONObject();
|
|
|
- boolean allSkipped = true;
|
|
|
- for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
|
|
|
- value.put(valueEntry.getKey(), valueEntry.getValue());
|
|
|
- allSkipped = false;
|
|
|
- }
|
|
|
- if (!allSkipped) {
|
|
|
- reallyAllSkipped = false;
|
|
|
- values.put(entryValues.getKey(), value);
|
|
|
- }
|
|
|
- }
|
|
|
- if (reallyAllSkipped) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- data.put("values", values);
|
|
|
- return data;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom single line chart.
|
|
|
- */
|
|
|
- public static class SingleLineChart extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<Integer> callable;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public SingleLineChart(String chartId, Callable<Integer> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- int value = callable.call();
|
|
|
- if (value == 0) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- data.put("value", value);
|
|
|
- return data;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom multi line chart.
|
|
|
- */
|
|
|
- public static class MultiLineChart extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<Map<String, Integer>> callable;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- JSONObject values = new JSONObject();
|
|
|
- Map<String, Integer> map = callable.call();
|
|
|
- if (map == null || map.isEmpty()) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- boolean allSkipped = true;
|
|
|
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
|
|
- if (entry.getValue() == 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- allSkipped = false;
|
|
|
- values.put(entry.getKey(), entry.getValue());
|
|
|
- }
|
|
|
- if (allSkipped) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- data.put("values", values);
|
|
|
- return data;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom simple bar chart.
|
|
|
- */
|
|
|
- public static class SimpleBarChart extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<Map<String, Integer>> callable;
|
|
|
-
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- JSONObject values = new JSONObject();
|
|
|
- Map<String, Integer> map = callable.call();
|
|
|
- if (map == null || map.isEmpty()) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
|
|
- JSONArray categoryValues = new JSONArray();
|
|
|
- categoryValues.add(entry.getValue());
|
|
|
- values.put(entry.getKey(), categoryValues);
|
|
|
- }
|
|
|
- data.put("values", values);
|
|
|
- return data;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * Represents a custom advanced bar chart.
|
|
|
- */
|
|
|
- public static class AdvancedBarChart extends CustomChart {
|
|
|
-
|
|
|
- private final Callable<Map<String, int[]>> callable;
|
|
|
+import javax.net.ssl.HttpsURLConnection;
|
|
|
|
|
|
-
|
|
|
- * Class constructor.
|
|
|
- *
|
|
|
- * @param chartId The id of the chart.
|
|
|
- * @param callable The callable which is used to request the chart data.
|
|
|
- */
|
|
|
- public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
|
|
|
- super(chartId);
|
|
|
- this.callable = callable;
|
|
|
- }
|
|
|
+import org.bukkit.plugin.Plugin;
|
|
|
|
|
|
- @Override
|
|
|
- protected JSONObject getChartData() throws Exception {
|
|
|
- JSONObject data = new JSONObject();
|
|
|
- JSONObject values = new JSONObject();
|
|
|
- Map<String, int[]> map = callable.call();
|
|
|
- if (map == null || map.isEmpty()) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- boolean allSkipped = true;
|
|
|
- for (Map.Entry<String, int[]> entry : map.entrySet()) {
|
|
|
- if (entry.getValue().length == 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- allSkipped = false;
|
|
|
- JSONArray categoryValues = new JSONArray();
|
|
|
- for (int categoryValue : entry.getValue()) {
|
|
|
- categoryValues.add(categoryValue);
|
|
|
- }
|
|
|
- values.put(entry.getKey(), categoryValues);
|
|
|
- }
|
|
|
- if (allSkipped) {
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- data.put("values", values);
|
|
|
- return data;
|
|
|
- }
|
|
|
+import com.google.gson.Gson;
|
|
|
|
|
|
- }
|
|
|
-}
|
|
|
+public class Metrics {
|
|
|
+ private Plugin pl;
|
|
|
+ private final Gson gson = new Gson();
|
|
|
+
|
|
|
+ private String URL = "https://spaceio.de/update/%s";
|
|
|
+
|
|
|
+ public Metrics(Plugin pl){
|
|
|
+ this.pl = pl;
|
|
|
+ URL = String.format(URL, pl.getName());
|
|
|
+ pl.getServer().getScheduler().runTaskTimerAsynchronously(pl, () -> {
|
|
|
+ String dataJson = collectData();
|
|
|
+ try{
|
|
|
+ sendData(dataJson);
|
|
|
+ }catch(Exception e){
|
|
|
+
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }, 20L * 5, 20L * 60 * 10);
|
|
|
+ }
|
|
|
+ private String collectData() {
|
|
|
+ Data data = new Data();
|
|
|
+
|
|
|
+
|
|
|
+ for(Plugin plug : pl.getServer().getPluginManager().getPlugins()) data.plugs.put(plug.getName(), plug.getDescription().getVersion());
|
|
|
+
|
|
|
+
|
|
|
+ data.onlinePlayers = pl.getServer().getOnlinePlayers().size();
|
|
|
+
|
|
|
+
|
|
|
+ data.serverVersion = getVersion();
|
|
|
+
|
|
|
+
|
|
|
+ data.coreCnt = Runtime.getRuntime().availableProcessors();
|
|
|
+
|
|
|
+
|
|
|
+ data.javaRuntime = System.getProperty("java.runtime.version");
|
|
|
+
|
|
|
+
|
|
|
+ data.onlineMode = pl.getServer().getOnlineMode();
|
|
|
+
|
|
|
+ return gson.toJson(data);
|
|
|
+ }
|
|
|
+ private void sendData(String dataJson) throws Exception{
|
|
|
+ java.net.URL obj = new java.net.URL(URL);
|
|
|
+ HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
|
|
|
+
|
|
|
+ con.setRequestMethod("POST");
|
|
|
+ con.setRequestProperty("User-Agent", "Java/Bukkit");
|
|
|
+
|
|
|
+ con.setDoOutput(true);
|
|
|
+ DataOutputStream wr = new DataOutputStream(con.getOutputStream());
|
|
|
+ wr.writeBytes(dataJson);
|
|
|
+ wr.flush();
|
|
|
+ wr.close();
|
|
|
+ con.getResponseCode();
|
|
|
+ }
|
|
|
+ private String getVersion(){
|
|
|
+ String packageName = pl.getServer().getClass().getPackage().getName();
|
|
|
+ return packageName.substring(packageName.lastIndexOf('.') + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+class Data {
|
|
|
+ HashMap<String, String> plugs = new HashMap<String, String>();
|
|
|
+ int onlinePlayers;
|
|
|
+ String serverVersion;
|
|
|
+ int coreCnt;
|
|
|
+ String javaRuntime;
|
|
|
+ boolean onlineMode;
|
|
|
+}
|