diff --git a/pom.xml b/pom.xml index 74b921f..2f32265 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/src/main/java/me/badbones69/crazyauctions/api/Category.java b/src/main/java/me/badbones69/crazyauctions/api/Category.java index 1bcad09..c7bcbf8 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/Category.java +++ b/src/main/java/me/badbones69/crazyauctions/api/Category.java @@ -26,13 +26,6 @@ public enum Category { this.Items = items; } - /** - * @return Returns the type name as a string. - */ - public String getName() { - return Name; - } - /** * @param name Name of the Type you want. * @return Returns the Type as a Enum. @@ -46,10 +39,6 @@ public enum Category { return null; } - public ArrayList getItems() { - return Items; - } - private static ArrayList getArmor() { ArrayList ma = new ArrayList<>(); if(Version.getCurrentVersion().isNewer(Version.v1_12_R1)) { @@ -186,4 +175,15 @@ public enum Category { return ma; } + /** + * @return Returns the type name as a string. + */ + public String getName() { + return Name; + } + + public ArrayList getItems() { + return Items; + } + } \ No newline at end of file diff --git a/src/main/java/me/badbones69/crazyauctions/api/FileManager.java b/src/main/java/me/badbones69/crazyauctions/api/FileManager.java index eaff5bd..a8cb22a 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/FileManager.java +++ b/src/main/java/me/badbones69/crazyauctions/api/FileManager.java @@ -19,6 +19,7 @@ import java.util.HashMap; */ public class FileManager { + private static FileManager instance = new FileManager(); private Plugin plugin; private String prefix = ""; private Boolean log = false; @@ -28,8 +29,6 @@ public class FileManager { private HashMap autoGenerateFiles = new HashMap<>(); private HashMap configurations = new HashMap<>(); - private static FileManager instance = new FileManager(); - public static FileManager getInstance() { return instance; } diff --git a/src/main/java/me/badbones69/crazyauctions/api/Messages.java b/src/main/java/me/badbones69/crazyauctions/api/Messages.java index d7cac07..55eadbd 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/Messages.java +++ b/src/main/java/me/badbones69/crazyauctions/api/Messages.java @@ -54,10 +54,10 @@ public enum Messages { "&9/Ah Listed - &eView and manage the items you are selling.", "&9/Ah Help - &eView this help menu.")); + private static FileManager fileManager = FileManager.getInstance(); private String path; private String defaultMessage; private List defaultListMessage; - private static FileManager fileManager = FileManager.getInstance(); private Messages(String path, String defaultMessage) { this.path = path; @@ -69,6 +69,43 @@ public enum Messages { this.defaultListMessage = defaultListMessage; } + public static String convertList(List list) { + String message = ""; + for(String m : list) { + message += Methods.color(m) + "\n"; + } + return message; + } + + public static String convertList(List list, HashMap placeholders) { + String message = ""; + for(String m : list) { + message += Methods.color(m) + "\n"; + } + for(String ph : placeholders.keySet()) { + message = Methods.color(message.replaceAll(ph, placeholders.get(ph))).replaceAll(ph, placeholders.get(ph).toLowerCase()); + } + return message; + } + + public static void addMissingMessages() { + FileConfiguration messages = Files.MESSAGES.getFile(); + boolean saveFile = false; + for(Messages message : values()) { + if(!messages.contains("Messages." + message.getPath())) { + saveFile = true; + if(message.getDefaultMessage() != null) { + messages.set("Messages." + message.getPath(), message.getDefaultMessage()); + }else { + messages.set("Messages." + message.getPath(), message.getDefaultListMessage()); + } + } + } + if(saveFile) { + Files.MESSAGES.saveFile(); + } + } + public String getMessage() { if(isList()) { if(exists()) { @@ -147,43 +184,6 @@ public enum Messages { return message; } - public static String convertList(List list) { - String message = ""; - for(String m : list) { - message += Methods.color(m) + "\n"; - } - return message; - } - - public static String convertList(List list, HashMap placeholders) { - String message = ""; - for(String m : list) { - message += Methods.color(m) + "\n"; - } - for(String ph : placeholders.keySet()) { - message = Methods.color(message.replaceAll(ph, placeholders.get(ph))).replaceAll(ph, placeholders.get(ph).toLowerCase()); - } - return message; - } - - public static void addMissingMessages() { - FileConfiguration messages = Files.MESSAGES.getFile(); - Boolean saveFile = false; - for(Messages message : values()) { - if(!messages.contains("Messages." + message.getPath())) { - saveFile = true; - if(message.getDefaultMessage() != null) { - messages.set("Messages." + message.getPath(), message.getDefaultMessage()); - }else { - messages.set("Messages." + message.getPath(), message.getDefaultListMessage()); - } - } - } - if(saveFile) { - Files.MESSAGES.saveFile(); - } - } - private Boolean exists() { return Files.MESSAGES.getFile().contains("Messages." + path); } diff --git a/src/main/java/me/badbones69/crazyauctions/api/ShopType.java b/src/main/java/me/badbones69/crazyauctions/api/ShopType.java index cd5ad76..eb55c08 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/ShopType.java +++ b/src/main/java/me/badbones69/crazyauctions/api/ShopType.java @@ -13,13 +13,6 @@ public enum ShopType { this.name = name; } - /** - * @return Returns the type name as a string. - */ - public String getName() { - return name; - } - /** * @param name name of the Type you want. * @return Returns the Type as a Enum. @@ -33,4 +26,11 @@ public enum ShopType { return null; } + /** + * @return Returns the type name as a string. + */ + public String getName() { + return name; + } + } diff --git a/src/main/java/me/badbones69/crazyauctions/api/Version.java b/src/main/java/me/badbones69/crazyauctions/api/Version.java index a71e1c2..893b301 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/Version.java +++ b/src/main/java/me/badbones69/crazyauctions/api/Version.java @@ -15,9 +15,9 @@ public enum Version { v1_14_R1(1141), TOO_NEW(-2); + public static Version currentVersion; private static Version latest; private Integer versionInteger; - public static Version currentVersion; private Version(int versionInteger) { this.versionInteger = versionInteger; @@ -47,14 +47,6 @@ public enum Version { return currentVersion; } - /** - * - * @return The server's minecraft version as an integer. - */ - public Integer getVersionInteger() { - return this.versionInteger; - } - /** * Get the latest version allowed by the Version class. * @return The latest version. @@ -73,6 +65,14 @@ public enum Version { } } + /** + * + * @return The server's minecraft version as an integer. + */ + public Integer getVersionInteger() { + return this.versionInteger; + } + /** * This checks if the current version is older, newer, or is the checked version. * @param version The version you are checking. diff --git a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionBuyEvent.java b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionBuyEvent.java index 3203445..58c1cdd 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionBuyEvent.java +++ b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionBuyEvent.java @@ -14,10 +14,10 @@ import org.bukkit.inventory.ItemStack; */ public class AuctionBuyEvent extends Event { + private static final HandlerList handlers = new HandlerList(); private Player player; private long price; private ItemStack item; - private static final HandlerList handlers = new HandlerList(); /** * @@ -31,11 +31,11 @@ public class AuctionBuyEvent extends Event { this.price = price; } - public HandlerList getHandlers() { + public static HandlerList getHandlerList() { return handlers; } - public static HandlerList getHandlerList() { + public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java index 9fb5203..507efad 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java +++ b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionCancelledEvent.java @@ -16,12 +16,12 @@ import org.bukkit.inventory.ItemStack; */ public class AuctionCancelledEvent extends Event { + private static final HandlerList handlers = new HandlerList(); private OfflinePlayer offlinePlayer; private Player onlinePlayer; private boolean isOnline; private ItemStack item; private CancelledReason reason; - private static final HandlerList handlers = new HandlerList(); /** * @@ -47,11 +47,11 @@ public class AuctionCancelledEvent extends Event { this.reason = reason; } - public HandlerList getHandlers() { + public static HandlerList getHandlerList() { return handlers; } - public static HandlerList getHandlerList() { + public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionExpireEvent.java b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionExpireEvent.java index 6e02728..dc2b4ca 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionExpireEvent.java +++ b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionExpireEvent.java @@ -15,11 +15,11 @@ import org.bukkit.inventory.ItemStack; */ public class AuctionExpireEvent extends Event { + private static final HandlerList handlers = new HandlerList(); private OfflinePlayer offlinePlayer; private Player onlinePlayer; private boolean isOnline; private ItemStack item; - private static final HandlerList handlers = new HandlerList(); /** * @@ -43,11 +43,11 @@ public class AuctionExpireEvent extends Event { this.isOnline = true; } - public HandlerList getHandlers() { + public static HandlerList getHandlerList() { return handlers; } - public static HandlerList getHandlerList() { + public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionListEvent.java b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionListEvent.java index b41aa6c..45a463d 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionListEvent.java +++ b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionListEvent.java @@ -15,11 +15,11 @@ import org.bukkit.inventory.ItemStack; */ public class AuctionListEvent extends Event { + private static final HandlerList handlers = new HandlerList(); private Player player; private long price; private ShopType shop; private ItemStack item; - private static final HandlerList handlers = new HandlerList(); /** * @@ -35,11 +35,11 @@ public class AuctionListEvent extends Event { this.price = price; } - public HandlerList getHandlers() { + public static HandlerList getHandlerList() { return handlers; } - public static HandlerList getHandlerList() { + public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java index 0a17d63..a0e8b00 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java +++ b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionNewBidEvent.java @@ -14,10 +14,10 @@ import org.bukkit.inventory.ItemStack; */ public class AuctionNewBidEvent extends Event { + private static final HandlerList handlers = new HandlerList(); private Player player; private long bid; private ItemStack item; - private static final HandlerList handlers = new HandlerList(); /** * @@ -31,11 +31,11 @@ public class AuctionNewBidEvent extends Event { this.bid = bid; } - public HandlerList getHandlers() { + public static HandlerList getHandlerList() { return handlers; } - public static HandlerList getHandlerList() { + public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java index 050842d..df23257 100644 --- a/src/main/java/me/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java +++ b/src/main/java/me/badbones69/crazyauctions/api/events/AuctionWinBidEvent.java @@ -14,10 +14,10 @@ import org.bukkit.inventory.ItemStack; */ public class AuctionWinBidEvent extends Event { + private static final HandlerList handlers = new HandlerList(); private Player player; private long bid; private ItemStack item; - private static final HandlerList handlers = new HandlerList(); /** * @@ -31,11 +31,11 @@ public class AuctionWinBidEvent extends Event { this.bid = bid; } - public HandlerList getHandlers() { + public static HandlerList getHandlerList() { return handlers; } - public static HandlerList getHandlerList() { + public HandlerList getHandlers() { return handlers; } diff --git a/src/main/java/me/badbones69/crazyauctions/controllers/GUI.java b/src/main/java/me/badbones69/crazyauctions/controllers/GUI.java index 7006a4e..9e3a62f 100644 --- a/src/main/java/me/badbones69/crazyauctions/controllers/GUI.java +++ b/src/main/java/me/badbones69/crazyauctions/controllers/GUI.java @@ -439,6 +439,30 @@ public class GUI implements Listener { return Methods.addLore(item.clone(), lore); } + private static void playClick(Player player) { + if(Files.CONFIG.getFile().contains("Settings.Sounds.Toggle")) { + if(Files.CONFIG.getFile().getBoolean("Settings.Sounds.Toggle")) { + String sound = Files.CONFIG.getFile().getString("Settings.Sounds.Sound"); + try { + player.playSound(player.getLocation(), Sound.valueOf(sound), 1, 1); + }catch(Exception e) { + if(Methods.getVersion() >= 191) { + player.playSound(player.getLocation(), Sound.valueOf("UI_BUTTON_CLICK"), 1, 1); + }else { + player.playSound(player.getLocation(), Sound.valueOf("CLICK"), 1, 1); + } + Bukkit.getLogger().log(Level.WARNING, "[Crazy Auctions]>> You set the sound to " + sound + " and this is not a sound for your minecraft version. " + "Please go to the config and set a correct sound or turn the sound off in the toggle setting."); + } + } + }else { + if(Methods.getVersion() >= 191) { + player.playSound(player.getLocation(), Sound.valueOf("UI_BUTTON_CLICK"), 1, 1); + }else { + player.playSound(player.getLocation(), Sound.valueOf("CLICK"), 1, 1); + } + } + } + @EventHandler public void onInvClose(InventoryCloseEvent e) { FileConfiguration config = Files.CONFIG.getFile(); @@ -926,28 +950,4 @@ public class GUI implements Listener { } } - private static void playClick(Player player) { - if(Files.CONFIG.getFile().contains("Settings.Sounds.Toggle")) { - if(Files.CONFIG.getFile().getBoolean("Settings.Sounds.Toggle")) { - String sound = Files.CONFIG.getFile().getString("Settings.Sounds.Sound"); - try { - player.playSound(player.getLocation(), Sound.valueOf(sound), 1, 1); - }catch(Exception e) { - if(Methods.getVersion() >= 191) { - player.playSound(player.getLocation(), Sound.valueOf("UI_BUTTON_CLICK"), 1, 1); - }else { - player.playSound(player.getLocation(), Sound.valueOf("CLICK"), 1, 1); - } - Bukkit.getLogger().log(Level.WARNING, "[Crazy Auctions]>> You set the sound to " + sound + " and this is not a sound for your minecraft version. " + "Please go to the config and set a correct sound or turn the sound off in the toggle setting."); - } - } - }else { - if(Methods.getVersion() >= 191) { - player.playSound(player.getLocation(), Sound.valueOf("UI_BUTTON_CLICK"), 1, 1); - }else { - player.playSound(player.getLocation(), Sound.valueOf("CLICK"), 1, 1); - } - } - } - } diff --git a/src/main/java/me/badbones69/crazyauctions/controllers/Metrics.java b/src/main/java/me/badbones69/crazyauctions/controllers/Metrics.java index 3ad3724..93884a3 100644 --- a/src/main/java/me/badbones69/crazyauctions/controllers/Metrics.java +++ b/src/main/java/me/badbones69/crazyauctions/controllers/Metrics.java @@ -27,669 +27,670 @@ import java.util.zip.GZIPOutputStream; */ @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; - - // A list with all custom charts - private final List charts = new ArrayList<>(); - - /** - * Class constructor. - * - * @param plugin The plugin which stats should be submitted. - */ - public Metrics(Plugin plugin) { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null!"); - } - 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); - - // 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.put("pluginName", pluginName); // Append the name of the plugin - data.put("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.put("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(); - - // 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.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(); - // 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 { - pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider())); - } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { } - } - } catch (NoSuchFieldException ignored) { } - } - - data.put("plugins", pluginData); - - // Create a new thread for the connection to the bStats server - new Thread(new Runnable() { - @Override - public void run() { - 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.toString()); - } - 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); - DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); - outputStream.write(compressedData); - outputStream.flush(); - outputStream.close(); - - InputStream inputStream = connection.getInputStream(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - - StringBuilder builder = new StringBuilder(); - String line; - while ((line = bufferedReader.readLine()) != null) { - builder.append(line); - } - bufferedReader.close(); - if (logResponseStatusText) { - plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString()); - } - } - - /** - * 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(StandardCharsets.UTF_8)); - gzip.close(); - 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.put("chartId", chartId); - try { - JSONObject data = getChartData(); - if (data == null) { - // If the data is null we don't send the chart. - 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 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.put("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.put(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - data.put("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.put(valueEntry.getKey(), valueEntry.getValue()); - allSkipped = false; - } - if (!allSkipped) { - reallyAllSkipped = false; - values.put(entryValues.getKey(), value); - } - } - if (reallyAllSkipped) { - // Null = skip the chart - return null; - } - data.put("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.put("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.put(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - data.put("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(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> 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(categoryValue); - } - values.put(entry.getKey(), categoryValues); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - data.put("values", values); - return data; - } - } - + + // 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"; + // 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; + + 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 plugin + private final Plugin plugin; + // A list with all custom charts + private final List charts = new ArrayList<>(); + // Is bStats enabled on this server? + private boolean enabled; + + /** + * Class constructor. + * + * @param plugin The plugin which stats should be submitted. + */ + public Metrics(Plugin plugin) { + if(plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null!"); + } + 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); + + // 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(); + } + } + } + + /** + * 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.toString()); + } + 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); + DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); + outputStream.write(compressedData); + outputStream.flush(); + outputStream.close(); + + InputStream inputStream = connection.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + StringBuilder builder = new StringBuilder(); + String line; + while((line = bufferedReader.readLine()) != null) { + builder.append(line); + } + bufferedReader.close(); + if(logResponseStatusText) { + plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString()); + } + } + + /** + * 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(StandardCharsets.UTF_8)); + gzip.close(); + return outputStream.toByteArray(); + } + + /** + * 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.put("pluginName", pluginName); // Append the name of the plugin + data.put("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.put("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(); + + // 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.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(); + // 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 { + pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider())); + }catch(NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { + } + } + }catch(NoSuchFieldException ignored) { + } + } + + data.put("plugins", pluginData); + + // Create a new thread for the connection to the bStats server + new Thread(new Runnable() { + @Override + public void run() { + 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(); + } + + /** + * 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.put("chartId", chartId); + try { + JSONObject data = getChartData(); + if(data == null) { + // If the data is null we don't send the chart. + 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 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.put("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.put(entry.getKey(), entry.getValue()); + } + if(allSkipped) { + // Null = skip the chart + return null; + } + data.put("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.put(valueEntry.getKey(), valueEntry.getValue()); + allSkipped = false; + } + if(!allSkipped) { + reallyAllSkipped = false; + values.put(entryValues.getKey(), value); + } + } + if(reallyAllSkipped) { + // Null = skip the chart + return null; + } + data.put("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.put("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.put(entry.getKey(), entry.getValue()); + } + if(allSkipped) { + // Null = skip the chart + return null; + } + data.put("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(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> 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(categoryValue); + } + values.put(entry.getKey(), categoryValues); + } + if(allSkipped) { + // Null = skip the chart + return null; + } + data.put("values", values); + return data; + } + + } + } \ No newline at end of file diff --git a/src/main/java/me/badbones69/crazyauctions/currency/CurrencyManager.java b/src/main/java/me/badbones69/crazyauctions/currency/CurrencyManager.java index 9e495c7..7a41598 100644 --- a/src/main/java/me/badbones69/crazyauctions/currency/CurrencyManager.java +++ b/src/main/java/me/badbones69/crazyauctions/currency/CurrencyManager.java @@ -22,20 +22,6 @@ public enum CurrencyManager { // Currency Manager this.name = name; } - /** - * @return Returns the Currency name as a string. - */ - public String getName() { - return name; - } - - /** - * @return Returns the Currency name as a string. - */ - public String getPluginName() { - return pluginName; - } - /** * @param name * name of the Type you want. @@ -50,17 +36,6 @@ public enum CurrencyManager { // Currency Manager return null; } - /** - * - * @return Returns true if the server has the plugin. - */ - public Boolean hasPlugin() { - if(Bukkit.getServer().getPluginManager().getPlugin(pluginName) != null) { - return Files.CONFIG.getFile().getBoolean("Settings.Currencies." + pluginName + ".Enabled"); - } - return false; - } - /** * * @param player @@ -115,4 +90,29 @@ public enum CurrencyManager { // Currency Manager Vault.addMoney(player, amount); } + /** + * @return Returns the Currency name as a string. + */ + public String getName() { + return name; + } + + /** + * @return Returns the Currency name as a string. + */ + public String getPluginName() { + return pluginName; + } + + /** + * + * @return Returns true if the server has the plugin. + */ + public Boolean hasPlugin() { + if(Bukkit.getServer().getPluginManager().getPlugin(pluginName) != null) { + return Files.CONFIG.getFile().getBoolean("Settings.Currencies." + pluginName + ".Enabled"); + } + return false; + } + } \ No newline at end of file