diff --git a/pom.xml b/pom.xml index 6db6020d..eaae8cf6 100644 --- a/pom.xml +++ b/pom.xml @@ -114,20 +114,25 @@ ess-repo https://ci.ender.zone/plugin/repository/everything/ + + + telesphoreo-repo + https://telesphoreo.me/repo/maven/ + org.projectlombok lombok - 1.18.12 + 1.18.16 provided commons-io commons-io - 2.7 + 2.8.0 compile @@ -141,35 +146,49 @@ commons-codec commons-codec - 1.14 + 1.15 + compile + + + + me.telesphoreo + mojangson + 1.0 + compile + + + + org.bstats + bstats-bukkit + 1.7 compile org.spigotmc spigot - 1.16.2-R0.1-SNAPSHOT + 1.16.3-R0.1-SNAPSHOT provided - com.github.TotalFreedom + com.github.TotalFreedomMC BukkitTelnet - 4.5-pre1 + 541e9fdb84 provided - com.github.TFPatches + com.github.TotalFreedomMC TF-LibsDisguises - 0cfa32159a + 48f01cf2fe provided com.sk89q.worldedit worldedit-bukkit - 7.1.0 + 7.2.0-SNAPSHOT provided @@ -232,19 +251,21 @@ org.reflections reflections - 0.9.11 + 0.9.12 + compile - javassist + org.javassist javassist - 3.12.1.GA + 3.27.0-GA + compile - com.github.TFPatches + com.github.TotalFreedomMC TFGuilds - ad93b9ed00 + db036fb187 provided @@ -252,6 +273,7 @@ org.apache.maven.plugins maven-checkstyle-plugin 3.1.1 + compile @@ -419,6 +441,10 @@ io.papermc.lib me.totalfreedom.totalfreedommod.paperlib + + org.bstats + me.totalfreedom.totalfreedommod + @@ -426,9 +452,11 @@ org.apache.commons:commons-lang3 commons-codec:commons-codec org.reflections:reflections - javassist:javassist + org.javassist:javassist me.rayzr522:jsonmessage io.papermc:paperlib + me.telesphoreo:mojangson + org.bstats:bstats-bukkit diff --git a/src/main/java/ca/momothereal/mojangson/MojangsonFinder.java b/src/main/java/ca/momothereal/mojangson/MojangsonFinder.java deleted file mode 100644 index 26d1c7c1..00000000 --- a/src/main/java/ca/momothereal/mojangson/MojangsonFinder.java +++ /dev/null @@ -1,23 +0,0 @@ -package ca.momothereal.mojangson; - -import ca.momothereal.mojangson.ex.MojangsonParseException; -import ca.momothereal.mojangson.value.MojangsonString; -import ca.momothereal.mojangson.value.MojangsonValue; - -public class MojangsonFinder -{ - - /** - * Automatically detects the appropriate MojangsonValue from the given value. - * - * @param value The value to parse - * @return The resulting MojangsonValue. If the type couldn't be found, it falls back to MojangsonString - * @throws MojangsonParseException if the given value could not be parsed - */ - public static MojangsonValue readFromValue(String value) throws MojangsonParseException - { - MojangsonValue val = new MojangsonString(); - val.read(value); - return val; - } -} diff --git a/src/main/java/ca/momothereal/mojangson/MojangsonToken.java b/src/main/java/ca/momothereal/mojangson/MojangsonToken.java deleted file mode 100644 index 3345887e..00000000 --- a/src/main/java/ca/momothereal/mojangson/MojangsonToken.java +++ /dev/null @@ -1,53 +0,0 @@ -package ca.momothereal.mojangson; - -public enum MojangsonToken -{ - - COMPOUND_START(0, "Compound_Start", '{'), - COMPOUND_END(1, "Compound_End", '}'), - ELEMENT_SEPERATOR(2, "Element_Seperator", ','), - ARRAY_START(3, "Array_Start", '['), - ARRAY_END(4, "Array_End", ']'), - ELEMENT_PAIR_SEPERATOR(5, "Pair_Seperator", ':'), - - STRING_QUOTES(6, "String_Quotes", '\"'), - DOUBLE_SUFFIX(8, "Double_Suffix", 'd'), - BYTE_SUFFIX(9, "Byte_Suffix", 'b'), - FLOAT_SUFFIX(10, "Float_Suffix", 'f'), - SHORT_SUFFIX(11, "Short_Suffix", 's'), - LONG_SUFFIX(12, "Long_Suffix", 'l'), - - WHITE_SPACE(13, "WhiteSpace", ' '); - - private int id; - private String name; - private char symbol; - - MojangsonToken(int id, String name, char symbol) - { - this.id = id; - this.name = name; - this.symbol = symbol; - } - - public int getId() - { - return id; - } - - public String getName() - { - return name; - } - - public char getSymbol() - { - return symbol; - } - - @Override - public String toString() - { - return String.valueOf(symbol); - } -} diff --git a/src/main/java/ca/momothereal/mojangson/ex/MojangsonParseException.java b/src/main/java/ca/momothereal/mojangson/ex/MojangsonParseException.java deleted file mode 100644 index 4409dcba..00000000 --- a/src/main/java/ca/momothereal/mojangson/ex/MojangsonParseException.java +++ /dev/null @@ -1,42 +0,0 @@ -package ca.momothereal.mojangson.ex; - -public class MojangsonParseException extends Exception -{ - - private ParseExceptionReason reason; - - public MojangsonParseException(String message, ParseExceptionReason reason) - { - super(message); - this.reason = reason; - } - - public ParseExceptionReason getReason() - { - return reason; - } - - @Override - public String getMessage() - { - return reason.getMessage() + ": " + super.getMessage(); - } - - public enum ParseExceptionReason - { - INVALID_FORMAT_NUM("Given value is not numerical"), - UNEXPECTED_SYMBOL("Unexpected symbol in Mojangson string"); - - private String message; - - ParseExceptionReason(String message) - { - this.message = message; - } - - public String getMessage() - { - return message; - } - } -} diff --git a/src/main/java/ca/momothereal/mojangson/value/MojangsonCompound.java b/src/main/java/ca/momothereal/mojangson/value/MojangsonCompound.java deleted file mode 100644 index b2bb6724..00000000 --- a/src/main/java/ca/momothereal/mojangson/value/MojangsonCompound.java +++ /dev/null @@ -1,144 +0,0 @@ -package ca.momothereal.mojangson.value; - -import ca.momothereal.mojangson.MojangsonFinder; -import ca.momothereal.mojangson.ex.MojangsonParseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import static ca.momothereal.mojangson.MojangsonToken.*; - -public class MojangsonCompound extends HashMap> implements MojangsonValue> -{ - - private final int C_COMPOUND_START = 0; // Parsing context - private final int C_COMPOUND_PAIR_KEY = 1; // Parsing context - private final int C_COMPOUND_PAIR_VALUE = 2; // Parsing context - - public MojangsonCompound() - { - - } - - public MojangsonCompound(Map map) - { - super(map); - } - - @Override - public void write(StringBuilder builder) - { - builder.append(COMPOUND_START); - boolean start = true; - - for (String key : keySet()) - { - if (start) - { - start = false; - } - else - { - builder.append(ELEMENT_SEPERATOR); - } - - builder.append(key).append(ELEMENT_PAIR_SEPERATOR); - List value = get(key); - for (MojangsonValue val : value) - { - val.write(builder); - } - } - builder.append(COMPOUND_END); - } - - @Override - public void read(String string) throws MojangsonParseException - { - int context = C_COMPOUND_START; - String tmp_key = "", tmp_val = ""; - int scope = 0; - boolean inString = false; - - for (int index = 0; index < string.length(); index++) - { - Character character = string.charAt(index); - - if (character == STRING_QUOTES.getSymbol()) - { - inString = !inString; - } - if (character == WHITE_SPACE.getSymbol()) - { - if (!inString) - { - continue; - } - } - if ((character == COMPOUND_START.getSymbol() || character == ARRAY_START.getSymbol()) && !inString) - { - scope++; - } - if ((character == COMPOUND_END.getSymbol() || character == ARRAY_END.getSymbol()) && !inString) - { - scope--; - } - if (context == C_COMPOUND_START) - { - if (character != COMPOUND_START.getSymbol()) - { - parseException(index, character); - return; - } - context++; - continue; - } - if (context == C_COMPOUND_PAIR_KEY) - { - if (character == ELEMENT_PAIR_SEPERATOR.getSymbol() && scope <= 1) - { - context++; - continue; - } - tmp_key += character; - continue; - } - if (context == C_COMPOUND_PAIR_VALUE) - { - if ((character == ELEMENT_SEPERATOR.getSymbol() || character == COMPOUND_END.getSymbol()) && scope <= 1 && !inString) - { - context = C_COMPOUND_PAIR_KEY; - computeIfAbsent(tmp_key, k -> new ArrayList<>()).add(MojangsonFinder.readFromValue(tmp_val)); - tmp_key = tmp_val = ""; - continue; - } - tmp_val += character; - } - } - } - - @Override - public Map getValue() - { - HashMap hack = new HashMap<>(); - for (String string : keySet()) - { - for (MojangsonValue value : get(string)) - { - hack.put(string, value); - } - } - return hack; - } - - @Override - public Class getValueClass() - { - return Map.class; - } - - private void parseException(int index, char symbol) throws MojangsonParseException - { - throw new MojangsonParseException("Index: " + index + ", symbol: \'" + symbol + "\'", MojangsonParseException.ParseExceptionReason.UNEXPECTED_SYMBOL); - } -} diff --git a/src/main/java/ca/momothereal/mojangson/value/MojangsonString.java b/src/main/java/ca/momothereal/mojangson/value/MojangsonString.java deleted file mode 100644 index 386b7974..00000000 --- a/src/main/java/ca/momothereal/mojangson/value/MojangsonString.java +++ /dev/null @@ -1,57 +0,0 @@ -package ca.momothereal.mojangson.value; - -import ca.momothereal.mojangson.MojangsonToken; -import ca.momothereal.mojangson.ex.MojangsonParseException; - -public class MojangsonString implements MojangsonValue -{ - private String value; - - public MojangsonString() - { - - } - - public MojangsonString(String value) - { - this.value = value; - } - - public String getValue() - { - return value; - } - - public void setValue(String value) - { - this.value = value; - } - - @Override - public void write(StringBuilder builder) - { - builder.append(MojangsonToken.STRING_QUOTES).append(value).append(MojangsonToken.STRING_QUOTES); - } - - @Override - public Class getValueClass() - { - return String.class; - } - - @Override - public void read(String string) throws MojangsonParseException - { - Character lastChar = string.charAt(string.length() - 1); - Character firstChar = string.charAt(0); - - if (firstChar == MojangsonToken.STRING_QUOTES.getSymbol() && lastChar == MojangsonToken.STRING_QUOTES.getSymbol()) - { - value = string.substring(1, string.length() - 1); - } - else - { - value = string; - } - } -} diff --git a/src/main/java/ca/momothereal/mojangson/value/MojangsonValue.java b/src/main/java/ca/momothereal/mojangson/value/MojangsonValue.java deleted file mode 100644 index 088238b4..00000000 --- a/src/main/java/ca/momothereal/mojangson/value/MojangsonValue.java +++ /dev/null @@ -1,42 +0,0 @@ -package ca.momothereal.mojangson.value; - -import ca.momothereal.mojangson.ex.MojangsonParseException; - -/** - * Represents a value inside a compound or array. - * - * @param The type of value this MojangsonValue holds - */ -public interface MojangsonValue -{ - - /** - * Writes the value to a StringBuilder buffer. - * - * @param builder The buffer to write to - */ - void write(StringBuilder builder); - - /** - * Parses and updates the current value to the given string representation - * - * @param string The string representation of the value - * @throws MojangsonParseException if the given value cannot be parsed - */ - void read(String string) throws MojangsonParseException; - - /** - * Gets the current literal value - * - * @return The current literal value of the MojangsonValue - */ - T getValue(); - - /** - * Gets the literal value's class - * - * @return The literal value's class - */ - Class getValueClass(); - -} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java index 7fc45659..034629a1 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java @@ -50,7 +50,7 @@ import me.totalfreedom.totalfreedommod.util.MethodTimer; import me.totalfreedom.totalfreedommod.world.CleanroomChunkGenerator; import me.totalfreedom.totalfreedommod.world.WorldManager; import me.totalfreedom.totalfreedommod.world.WorldRestrictions; -import org.bstats.Metrics; +import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java index 36bf5758..50ab4b63 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java @@ -13,7 +13,6 @@ import org.bukkit.entity.Player; @CommandParameters(description = "Shows the amount of coins you have or another player has", usage = "/ [playername]") public class Command_coins extends FreedomCommand { - @Override public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) { diff --git a/src/main/java/me/totalfreedom/totalfreedommod/sql/SQLite.java b/src/main/java/me/totalfreedom/totalfreedommod/sql/SQLite.java index 91b453b2..ce5fb786 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/sql/SQLite.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/sql/SQLite.java @@ -93,7 +93,7 @@ public class SQLite extends FreedomService { try { - connection.createStatement().execute("CREATE TABLE `players` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `notes` VARCHAR, `tag` VARCHAR, `discord_id` VARCHAR, `backup_codes` VARCHAR, `donator` BOOLEAN NOT NULL, `master_builder` BOOLEAN NOT NULL,`verification` BOOLEAN NOT NULL, `ride_mode` VARCHAR NOT NULL, `coins` INT NOT NULL, `items` VARCHAR, `total_votes` INT NOT NULL, `display_discord` BOOLEAN NOT NULL, `reddit_username` VARCHAR NOT NULL, `login_message` VARCHAR);"); + connection.createStatement().execute("CREATE TABLE `players` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `notes` VARCHAR, `tag` VARCHAR, `discord_id` VARCHAR, `backup_codes` VARCHAR, `donator` BOOLEAN NOT NULL, `master_builder` BOOLEAN NOT NULL,`verification` BOOLEAN NOT NULL, `ride_mode` VARCHAR NOT NULL, `coins` INT NOT NULL, `items` VARCHAR, `total_votes` INT NOT NULL, `display_discord` BOOLEAN NOT NULL, `reddit_username` VARCHAR, `login_message` VARCHAR);"); } catch (SQLException e) { diff --git a/src/main/java/org/bstats/Metrics.java b/src/main/java/org/bstats/Metrics.java deleted file mode 100644 index 4fd5ae54..00000000 --- a/src/main/java/org/bstats/Metrics.java +++ /dev/null @@ -1,847 +0,0 @@ -package org.bstats; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.nio.charset.StandardCharsets; -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; -import javax.net.ssl.HttpsURLConnection; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.ServicePriority; - -/** - * bStats collects some data for plugin authors. - *

- * Check out https://bStats.org/ to learn more about bStats! - */ -@SuppressWarnings({"WeakerAccess", "unused"}) -public class Metrics -{ - static - { - // You can use the property to disable the check in your test environment - if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) - { - // Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D - 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'}); - // We want to make sure nobody just copy & pastes the example and use the wrong package names - if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) - { - throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); - } - } - } - - // The version of this bStats class - public static final int B_STATS_VERSION = 1; - - // The url to which the data is sent - private static final String URL = "https://bStats.org/submitData/bukkit"; - - // Is bStats enabled on this server? - private boolean enabled; - - // Should failed requests be logged? - private static boolean logFailedRequests; - - // Should the sent data be logged? - private static boolean logSentData; - - // Should the response text be logged? - private static boolean logResponseStatusText; - - // The uuid of the server - private static String serverUUID; - - // The plugin - private final Plugin plugin; - - // The plugin id - private final int pluginId; - - // A list with all custom charts - private final List charts = new ArrayList<>(); - - /** - * Class constructor. - * - * @param plugin The plugin which stats should be submitted. - * @param pluginId The id of the plugin. - * It can be found at What is my plugin id? - */ - public Metrics(Plugin plugin, int pluginId) - { - if (plugin == null) - { - throw new IllegalArgumentException("Plugin cannot be null!"); - } - this.plugin = plugin; - this.pluginId = pluginId; - - // Get the config file - File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - - // Check if the config file exists - if (!config.isSet("serverUuid")) - { - - // Add default values - config.addDefault("enabled", true); - // Every server gets it's unique random id. - config.addDefault("serverUuid", UUID.randomUUID().toString()); - // Should failed request be logged? - config.addDefault("logFailedRequests", false); - // Should the sent data be logged? - config.addDefault("logSentData", false); - // Should the response text be logged? - config.addDefault("logResponseStatusText", false); - - // Inform the server owners about bStats - 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) - { - } - } - - // Load the data - enabled = config.getBoolean("enabled", true); - serverUUID = config.getString("serverUuid"); - logFailedRequests = config.getBoolean("logFailedRequests", false); - logSentData = config.getBoolean("logSentData", false); - logResponseStatusText = config.getBoolean("logResponseStatusText", false); - - if (enabled) - { - boolean found = false; - // Search for all other bStats Metrics classes to see if we are the first one - for (Class service : Bukkit.getServicesManager().getKnownServices()) - { - try - { - service.getField("B_STATS_VERSION"); // Our identifier :) - found = true; // We aren't the first - break; - } - catch (NoSuchFieldException ignored) - { - } - } - // Register our service - Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal); - if (!found) - { - // We are the first! - startSubmitting(); - } - } - } - - /** - * Checks if bStats is enabled. - * - * @return Whether bStats is enabled or not. - */ - public boolean isEnabled() - { - return enabled; - } - - /** - * 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); // We use a timer cause the Bukkit scheduler is affected by server lags - timer.scheduleAtFixedRate(new TimerTask() - { - @Override - public void run() - { - if (!plugin.isEnabled()) - { // Plugin was disabled - timer.cancel(); - return; - } - // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler - // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) - Bukkit.getScheduler().runTask(plugin, () -> submitData()); - } - }, 1000 * 60 * 5, 1000 * 60 * 30); - // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start - // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! - // WARNING: Just don't do it! - } - - /** - * 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.addProperty("pluginName", pluginName); // Append the name of the plugin - data.addProperty("id", pluginId); // Append the id of the plugin - data.addProperty("pluginVersion", pluginVersion); // Append the version of the plugin - JsonArray customCharts = new JsonArray(); - for (CustomChart customChart : charts) - { - // Add the data of the custom charts - JsonObject chart = customChart.getRequestJsonObject(); - if (chart == null) - { // If the chart is null, we skip it - continue; - } - customCharts.add(chart); - } - data.add("customCharts", customCharts); - - return data; - } - - /** - * Gets the server specific data. - * - * @return The server specific data. - */ - private JsonObject getServerData() - { - // Minecraft specific data - int playerAmount; - try - { - // Around MC 1.8 the return type was changed to a collection from an array, - // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - 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(); // Just use the new method if the Reflection failed - } - int onlineMode = Bukkit.getOnlineMode() ? 1 : 0; - String bukkitVersion = Bukkit.getVersion(); - String bukkitName = Bukkit.getName(); - - // OS/Java specific data - 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.addProperty("serverUUID", serverUUID); - - data.addProperty("playerAmount", playerAmount); - data.addProperty("onlineMode", onlineMode); - data.addProperty("bukkitVersion", bukkitVersion); - data.addProperty("bukkitName", bukkitName); - - data.addProperty("javaVersion", javaVersion); - data.addProperty("osName", osName); - data.addProperty("osArch", osArch); - data.addProperty("osVersion", osVersion); - data.addProperty("coreCount", coreCount); - - return data; - } - - /** - * Collects the data and sends it afterwards. - */ - private void submitData() - { - final JsonObject data = getServerData(); - - JsonArray pluginData = new JsonArray(); - // Search for all other bStats Metrics classes to get their plugin data - for (Class service : Bukkit.getServicesManager().getKnownServices()) - { - try - { - service.getField("B_STATS_VERSION"); // Our identifier :) - - for (RegisteredServiceProvider provider : Bukkit.getServicesManager().getRegistrations(service)) - { - try - { - Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider()); - if (plugin instanceof JsonObject) - { - pluginData.add((JsonObject)plugin); - } - else - { // old bstats version compatibility - try - { - Class jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject"); - if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) - { - Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString"); - jsonStringGetter.setAccessible(true); - String jsonString = (String)jsonStringGetter.invoke(plugin); - JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject(); - pluginData.add(object); - } - } - catch (ClassNotFoundException e) - { - // minecraft version 1.14+ - if (logFailedRequests) - { - this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception", e); - } - } - } - } - catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) - { - } - } - } - catch (NoSuchFieldException ignored) - { - } - } - - data.add("plugins", pluginData); - - // Create a new thread for the connection to the bStats server - new Thread(() -> - { - try - { - // Send the data - sendData(plugin, data); - } - catch (Exception e) - { - // Something went wrong! :( - 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 plugin Any plugin. It's just used to get a logger instance. - * @param data The data to send. - * @throws Exception If the request failed. - */ - private static void sendData(Plugin plugin, 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!"); - } - if (logSentData) - { - plugin.getLogger().info("Sending data to bStats: " + data); - } - HttpsURLConnection connection = (HttpsURLConnection)new URL(URL).openConnection(); - - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - - // Add headers - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format - connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); - - // Send data - connection.setDoOutput(true); - try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) - { - outputStream.write(compressedData); - } - - StringBuilder builder = new StringBuilder(); - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) - { - String line; - while ((line = bufferedReader.readLine()) != null) - { - builder.append(line); - } - } - - if (logResponseStatusText) - { - plugin.getLogger().info("Sent data to bStats and received response: " + builder); - } - } - - /** - * 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(); - try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) - { - gzip.write(str.getBytes(StandardCharsets.UTF_8)); - } - return outputStream.toByteArray(); - } - - /** - * Represents a custom chart. - */ - public static abstract class CustomChart - { - - // The id of the chart - 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.addProperty("chartId", chartId); - try - { - JsonObject data = getChartData(); - if (data == null) - { - // If the data is null we don't send the chart. - return null; - } - chart.add("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 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 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()) - { - // Null = skip the chart - return null; - } - data.addProperty("value", value); - return data; - } - } - - /** - * Represents a custom advanced pie. - */ - public static class AdvancedPie extends CustomChart - { - - private final Callable> 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> callable) - { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObject getChartData() throws Exception - { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); - Map map = callable.call(); - if (map == null || map.isEmpty()) - { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) - { - if (entry.getValue() == 0) - { - continue; // Skip this invalid - } - allSkipped = false; - values.addProperty(entry.getKey(), entry.getValue()); - } - if (allSkipped) - { - // Null = skip the chart - return null; - } - data.add("values", values); - return data; - } - } - - /** - * Represents a custom drilldown pie. - */ - public static class DrilldownPie extends CustomChart - { - - private final Callable>> 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>> callable) - { - super(chartId); - this.callable = callable; - } - - @Override - public JsonObject getChartData() throws Exception - { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); - Map> map = callable.call(); - if (map == null || map.isEmpty()) - { - // Null = skip the chart - return null; - } - boolean reallyAllSkipped = true; - for (Map.Entry> entryValues : map.entrySet()) - { - JsonObject value = new JsonObject(); - boolean allSkipped = true; - for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) - { - value.addProperty(valueEntry.getKey(), valueEntry.getValue()); - allSkipped = false; - } - if (!allSkipped) - { - reallyAllSkipped = false; - values.add(entryValues.getKey(), value); - } - } - if (reallyAllSkipped) - { - // Null = skip the chart - return null; - } - data.add("values", values); - return data; - } - } - - /** - * Represents a custom single line chart. - */ - public static class SingleLineChart extends CustomChart - { - - private final Callable 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 callable) - { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObject getChartData() throws Exception - { - JsonObject data = new JsonObject(); - int value = callable.call(); - if (value == 0) - { - // Null = skip the chart - return null; - } - data.addProperty("value", value); - return data; - } - - } - - /** - * Represents a custom multi line chart. - */ - public static class MultiLineChart extends CustomChart - { - - private final Callable> 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> callable) - { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObject getChartData() throws Exception - { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); - Map map = callable.call(); - if (map == null || map.isEmpty()) - { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) - { - if (entry.getValue() == 0) - { - continue; // Skip this invalid - } - allSkipped = false; - values.addProperty(entry.getKey(), entry.getValue()); - } - if (allSkipped) - { - // Null = skip the chart - return null; - } - data.add("values", values); - return data; - } - - } - - /** - * Represents a custom simple bar chart. - */ - public static class SimpleBarChart extends CustomChart - { - - private final Callable> 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> callable) - { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObject getChartData() throws Exception - { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); - Map map = callable.call(); - if (map == null || map.isEmpty()) - { - // Null = skip the chart - return null; - } - for (Map.Entry entry : map.entrySet()) - { - JsonArray categoryValues = new JsonArray(); - categoryValues.add(new JsonPrimitive(entry.getValue())); - values.add(entry.getKey(), categoryValues); - } - data.add("values", values); - return data; - } - - } - - /** - * Represents a custom advanced bar chart. - */ - public static class AdvancedBarChart extends CustomChart - { - - private final Callable> callable; - - /** - * 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> callable) - { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObject getChartData() throws Exception - { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); - Map map = callable.call(); - if (map == null || map.isEmpty()) - { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) - { - if (entry.getValue().length == 0) - { - continue; // Skip this invalid - } - allSkipped = false; - JsonArray categoryValues = new JsonArray(); - for (int categoryValue : entry.getValue()) - { - categoryValues.add(new JsonPrimitive(categoryValue)); - } - values.add(entry.getKey(), categoryValues); - } - if (allSkipped) - { - // Null = skip the chart - return null; - } - data.add("values", values); - return data; - } - } -} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 316cb770..13f36a8e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -150,12 +150,12 @@ shop: login_messages: - '%name% is a terrible %coloredrank%' - 'that %name% dude is a shitty %coloredrank%' - - 'Hi, my name is %name% and I'm %art% %coloredrank%&b that wasted coins on this login message.' + - 'Hi, my name is %name% and I''m %art% %coloredrank%&b that wasted coins on this login message.' - '&aDo not fear, %coloredrank% &b%name% &ais here!' - '%name% is %art% %coloredrank%&b, say hi to them before they gets banned for doing something stupid' - - 'Oh. It's &l%name%&r&b the %coloredrank%&b again. Great.' + - 'Oh. It''s &l%name%&r&b the %coloredrank%&b again. Great.' - 'Make way for %name% the %coloredrank%&b!' - - 'It's a bird! It's a plane! No, it's %art% %rank%! It's %name%' + - 'It''s a bird! It''s a plane! No, it''s %art% %rank%! It''s %name%' - '%rank% %name%' - '%coloredrank%&b %name%' - 'A wild %name%, %art% %coloredrank%&b, appeared!' @@ -163,6 +163,7 @@ shop: - '&a%name% &bis a a geeky &6%rank%' - '%name% is the %rank% who just exists' - '%name% based cringe poggers based based %rank%' + - '%name% thinks that &dWindows Server 2019 &bis the best server OS' # Item prices prices: