mirror of
https://github.com/BGHDDevelopment/PlayerBalancer.git
synced 2025-02-21 14:21:30 +01:00
Shading bStats with maven
This commit is contained in:
parent
f06f8f0920
commit
0da4cba109
@ -116,6 +116,7 @@
|
|||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.2" level="project" />
|
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.2" level="project" />
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
|
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.2" level="project" />
|
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.bstats:bstats-bungeecord:1.0" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||||
</component>
|
</component>
|
||||||
|
24
pom.xml
24
pom.xml
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>me.jaimemartz</groupId>
|
<groupId>me.jaimemartz</groupId>
|
||||||
<artifactId>lobbybalancer</artifactId>
|
<artifactId>lobbybalancer</artifactId>
|
||||||
<version>2.0.9.2</version>
|
<version>2.0.9.3</version>
|
||||||
<name>LobbyBalancer</name>
|
<name>LobbyBalancer</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@ -30,6 +30,10 @@
|
|||||||
<id>xephi-repo</id>
|
<id>xephi-repo</id>
|
||||||
<url>http://ci.xephi.fr/plugin/repository/everything/</url>
|
<url>http://ci.xephi.fr/plugin/repository/everything/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>bstats-repo</id>
|
||||||
|
<url>https://repo.bstats.org/content/groups/public/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<build>
|
<build>
|
||||||
<defaultGoal>clean install</defaultGoal>
|
<defaultGoal>clean install</defaultGoal>
|
||||||
@ -47,15 +51,21 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>2.4.3</version>
|
<version>2.4.3</version>
|
||||||
|
<configuration>
|
||||||
|
<minimizeJar>true</minimizeJar>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.bstats</pattern>
|
||||||
|
<shadedPattern>me.jaimemartz.lobbybalancer</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>shade</goal>
|
<goal>shade</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
|
||||||
<minimizeJar>true</minimizeJar>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -98,6 +108,12 @@
|
|||||||
<version>2.8.0</version>
|
<version>2.8.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bstats</groupId>
|
||||||
|
<artifactId>bstats-bungeecord</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
@ -14,11 +14,11 @@ import me.jaimemartz.lobbybalancer.manager.PlayerLocker;
|
|||||||
import me.jaimemartz.lobbybalancer.ping.PingManager;
|
import me.jaimemartz.lobbybalancer.ping.PingManager;
|
||||||
import me.jaimemartz.lobbybalancer.section.SectionManager;
|
import me.jaimemartz.lobbybalancer.section.SectionManager;
|
||||||
import me.jaimemartz.lobbybalancer.utils.DigitUtils;
|
import me.jaimemartz.lobbybalancer.utils.DigitUtils;
|
||||||
import me.jaimemartz.lobbybalancer.utils.Metrics;
|
|
||||||
import net.md_5.bungee.api.plugin.Command;
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
import net.md_5.bungee.api.plugin.Listener;
|
import net.md_5.bungee.api.plugin.Listener;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.config.Configuration;
|
import net.md_5.bungee.config.Configuration;
|
||||||
|
import org.bstats.Metrics;
|
||||||
import org.inventivetalent.update.bungee.BungeeUpdater;
|
import org.inventivetalent.update.bungee.BungeeUpdater;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -53,16 +53,14 @@ public class LobbyBalancer extends Plugin {
|
|||||||
|
|
||||||
this.enable();
|
this.enable();
|
||||||
|
|
||||||
if (ConfigEntries.SUBMIT_STATS.get()) {
|
//Metrics (https://bstats.org/)
|
||||||
//Metrics (https://bstats.org/)
|
Metrics metrics = new Metrics(this);
|
||||||
Metrics metrics = new Metrics(this);
|
metrics.addCustomChart(new Metrics.SingleLineChart("configured_sections") {
|
||||||
metrics.addCustomChart(new Metrics.SingleLineChart("configured_sections") {
|
@Override
|
||||||
@Override
|
public int getValue() {
|
||||||
public int getValue() {
|
return sectionManager.getSections().size();
|
||||||
return sectionManager.getSections().size();
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enable() {
|
private void enable() {
|
||||||
@ -113,7 +111,6 @@ public class LobbyBalancer extends Plugin {
|
|||||||
|
|
||||||
if (ConfigEntries.SERVER_CHECK_ENABLED.get()) {
|
if (ConfigEntries.SERVER_CHECK_ENABLED.get()) {
|
||||||
pingManager = new PingManager(this);
|
pingManager = new PingManager(this);
|
||||||
pingManager.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigEntries.FALLBACK_COMMAND_ENABLED.get()) {
|
if (ConfigEntries.FALLBACK_COMMAND_ENABLED.get()) {
|
||||||
@ -174,6 +171,7 @@ public class LobbyBalancer extends Plugin {
|
|||||||
|
|
||||||
if (ConfigEntries.SERVER_CHECK_ENABLED.get()) {
|
if (ConfigEntries.SERVER_CHECK_ENABLED.get()) {
|
||||||
pingManager.stop();
|
pingManager.stop();
|
||||||
|
pingManager = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigEntries.FALLBACK_COMMAND_ENABLED.get()) {
|
if (ConfigEntries.FALLBACK_COMMAND_ENABLED.get()) {
|
||||||
|
@ -62,7 +62,7 @@ public class FallbackCommand extends Command {
|
|||||||
try {
|
try {
|
||||||
ServerSection section = callable.call();
|
ServerSection section = callable.call();
|
||||||
if (section != null) {
|
if (section != null) {
|
||||||
ConnectionIntent.simple(plugin, player, section);
|
ConnectionIntent.connect(plugin, player, section);
|
||||||
} else {
|
} else {
|
||||||
msgr.send(ConfigEntries.UNAVAILABLE_MESSAGE.get());
|
msgr.send(ConfigEntries.UNAVAILABLE_MESSAGE.get());
|
||||||
}
|
}
|
||||||
|
@ -42,13 +42,13 @@ public class ManageCommand extends Command {
|
|||||||
if (args.length == 3) {
|
if (args.length == 3) {
|
||||||
ProxiedPlayer player = plugin.getProxy().getPlayer(args[2]);
|
ProxiedPlayer player = plugin.getProxy().getPlayer(args[2]);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
ConnectionIntent.simple(plugin, player, section);
|
ConnectionIntent.connect(plugin, player, section);
|
||||||
} else {
|
} else {
|
||||||
msgr.send("&cThere is no player with that name connected to this proxy");
|
msgr.send("&cThere is no player with that name connected to this proxy");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sender instanceof ProxiedPlayer) {
|
if (sender instanceof ProxiedPlayer) {
|
||||||
ConnectionIntent.simple(plugin, (ProxiedPlayer) sender, section);
|
ConnectionIntent.connect(plugin, (ProxiedPlayer) sender, section);
|
||||||
} else {
|
} else {
|
||||||
msgr.send("&cThis command can only be executed by a player");
|
msgr.send("&cThis command can only be executed by a player");
|
||||||
}
|
}
|
||||||
@ -110,7 +110,6 @@ public class ManageCommand extends Command {
|
|||||||
msgr.send("&7Valid: &b{status}",
|
msgr.send("&7Valid: &b{status}",
|
||||||
new Replacement("{status}", section.isValid() ? ChatColor.GREEN + "yes" : ChatColor.RED + "no"));
|
new Replacement("{status}", section.isValid() ? ChatColor.GREEN + "yes" : ChatColor.RED + "no"));
|
||||||
|
|
||||||
|
|
||||||
if (!section.getServers().isEmpty()) {
|
if (!section.getServers().isEmpty()) {
|
||||||
msgr.send("&7Section Servers: ");
|
msgr.send("&7Section Servers: ");
|
||||||
section.getServers().forEach(server -> {
|
section.getServers().forEach(server -> {
|
||||||
@ -164,7 +163,6 @@ public class ManageCommand extends Command {
|
|||||||
message.addExtra(extra);
|
message.addExtra(extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sender.sendMessage(message);
|
sender.sendMessage(message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ public class ConfigEntries implements ConfigEntryHolder {
|
|||||||
public static final ConfigEntry<Boolean> PLUGIN_ENABLED = new ConfigEntry<>(0, "settings.enabled", false);
|
public static final ConfigEntry<Boolean> PLUGIN_ENABLED = new ConfigEntry<>(0, "settings.enabled", false);
|
||||||
public static final ConfigEntry<Boolean> SILENT_STARTUP = new ConfigEntry<>(0, "settings.silent-startup", false);
|
public static final ConfigEntry<Boolean> SILENT_STARTUP = new ConfigEntry<>(0, "settings.silent-startup", false);
|
||||||
public static final ConfigEntry<Boolean> CHECK_UPDATES_ENABLED = new ConfigEntry<>(0, "settings.check-updates", true);
|
public static final ConfigEntry<Boolean> CHECK_UPDATES_ENABLED = new ConfigEntry<>(0, "settings.check-updates", true);
|
||||||
public static final ConfigEntry<Boolean> SUBMIT_STATS = new ConfigEntry<>(0, "settings.submit-stats", true);
|
|
||||||
|
|
||||||
public static final ConfigEntry<Boolean> SERVER_CHECK_ENABLED = new ConfigEntry<>(0, "settings.server-check.enabled", true);
|
public static final ConfigEntry<Boolean> SERVER_CHECK_ENABLED = new ConfigEntry<>(0, "settings.server-check.enabled", true);
|
||||||
public static final ConfigEntry<String> SERVER_CHECK_MODE = new ConfigEntry<>(0, "settings.server-check.tactic", "CUSTOM");
|
public static final ConfigEntry<String> SERVER_CHECK_MODE = new ConfigEntry<>(0, "settings.server-check.tactic", "CUSTOM");
|
||||||
|
@ -52,7 +52,7 @@ public abstract class ConnectionIntent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final ServerInfo fetchServer(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section, ProviderType provider, List<ServerInfo> servers) {
|
private ServerInfo fetchServer(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section, ProviderType provider, List<ServerInfo> servers) {
|
||||||
if (ConfigEntries.ASSIGN_TARGETS_ENABLED.get()) {
|
if (ConfigEntries.ASSIGN_TARGETS_ENABLED.get()) {
|
||||||
if (ServerAssignRegistry.hasAssignedServer(player, section)) {
|
if (ServerAssignRegistry.hasAssignedServer(player, section)) {
|
||||||
ServerInfo target = ServerAssignRegistry.getAssignedServer(player, section);
|
ServerInfo target = ServerAssignRegistry.getAssignedServer(player, section);
|
||||||
@ -66,7 +66,7 @@ public abstract class ConnectionIntent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int intents = ConfigEntries.SERVER_CHECK_ATTEMPTS.get();
|
int intents = ConfigEntries.SERVER_CHECK_ATTEMPTS.get();
|
||||||
while (intents-- >= 1) {
|
for (int intent = 1; intent <= intents; intent++) {
|
||||||
if (servers.size() == 0) return null;
|
if (servers.size() == 0) return null;
|
||||||
if (servers.size() == 1) return servers.get(0);
|
if (servers.size() == 1) return servers.get(0);
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ public abstract class ConnectionIntent {
|
|||||||
servers.remove(target);
|
servers.remove(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ public abstract class ConnectionIntent {
|
|||||||
//Nothing to do
|
//Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void simple(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section) {
|
public static void connect(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section) {
|
||||||
new ConnectionIntent(plugin, player, section) {
|
new ConnectionIntent(plugin, player, section) {
|
||||||
@Override
|
@Override
|
||||||
public void connect(ServerInfo server) {
|
public void connect(ServerInfo server) {
|
||||||
|
@ -39,7 +39,7 @@ public class PluginMessageListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionIntent.simple(plugin, player, section);
|
ConnectionIntent.connect(plugin, player, section);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ public class PluginMessageListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionIntent.simple(plugin, player, section);
|
ConnectionIntent.connect(plugin, player, section);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ public class ServerConnectListener implements Listener {
|
|||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onConnect(ServerConnectEvent event) {
|
public void onConnect(ServerConnectEvent event) {
|
||||||
ProxiedPlayer player = event.getPlayer();
|
ProxiedPlayer player = event.getPlayer();
|
||||||
|
|
||||||
ServerInfo target = event.getTarget();
|
ServerInfo target = event.getTarget();
|
||||||
Messager msgr = new Messager(player);
|
Messager msgr = new Messager(player);
|
||||||
|
|
||||||
ServerSection section = plugin.getSectionManager().getByServer(target);
|
ServerSection section = plugin.getSectionManager().getByServer(target);
|
||||||
|
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
|
@ -111,7 +111,7 @@ public class ServerKickListener implements Listener {
|
|||||||
event.setCancelServer(server);
|
event.setCancelServer(server);
|
||||||
plugin.getProxy().getScheduler().schedule(plugin, () -> {
|
plugin.getProxy().getScheduler().schedule(plugin, () -> {
|
||||||
PlayerLocker.unlock(player);
|
PlayerLocker.unlock(player);
|
||||||
}, 2, TimeUnit.SECONDS);
|
}, 5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,17 +11,12 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class PingManager {
|
public class PingManager {
|
||||||
private final LobbyBalancer plugin;
|
|
||||||
private boolean stopped = true;
|
private boolean stopped = true;
|
||||||
private PingTactic tactic;
|
private PingTactic tactic;
|
||||||
private ScheduledTask task;
|
private ScheduledTask task;
|
||||||
private final Map<ServerInfo, ServerStatus> storage = new HashMap<>();
|
private final Map<ServerInfo, ServerStatus> storage = new HashMap<>();
|
||||||
|
|
||||||
public PingManager(LobbyBalancer plugin) {
|
public PingManager(LobbyBalancer plugin) {
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
@ -41,7 +36,7 @@ public class PingManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
track(server);
|
track(plugin, server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0L, ConfigEntries.SERVER_CHECK_INTERVAL.get(), TimeUnit.MILLISECONDS);
|
}, 0L, ConfigEntries.SERVER_CHECK_INTERVAL.get(), TimeUnit.MILLISECONDS);
|
||||||
@ -55,17 +50,15 @@ public class PingManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void track(ServerInfo server) {
|
private void track(LobbyBalancer plugin, ServerInfo server) {
|
||||||
tactic.ping(server, (status, throwable) -> {
|
tactic.ping(server, (status, throwable) -> {
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
status = new ServerStatus("Server Unreachable", 0, 0);
|
status = new ServerStatus("Server Unreachable", 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigEntries.SERVER_CHECK_PRINT_INFO.get()) {
|
if (ConfigEntries.SERVER_CHECK_PRINT_INFO.get()) {
|
||||||
plugin.getLogger().info(String.format(
|
plugin.getLogger().info(String.format("Tracking server %s, status: [Description: \"%s\", Online Players: %s, Maximum Players: %s, Accessible: %s]",
|
||||||
"Tracking server %s, status: [Description: \"%s\", Online Players: %s, Maximum Players: %s, Accessible: %s]",
|
server.getName(), status.getDescription(), status.getOnlinePlayers(), status.getMaximumPlayers(), status.isAccessible()));
|
||||||
server.getName(), status.getDescription(), status.getOnlinePlayers(), status.getMaximumPlayers(), status.isAccessible()
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.put(server, status);
|
storage.put(server, status);
|
||||||
|
@ -26,7 +26,7 @@ public class SectionCommand extends Command {
|
|||||||
Messager msgr = new Messager(sender);
|
Messager msgr = new Messager(sender);
|
||||||
if (sender instanceof ProxiedPlayer) {
|
if (sender instanceof ProxiedPlayer) {
|
||||||
ProxiedPlayer player = (ProxiedPlayer) sender;
|
ProxiedPlayer player = (ProxiedPlayer) sender;
|
||||||
ConnectionIntent.simple(plugin, player, section);
|
ConnectionIntent.connect(plugin, player, section);
|
||||||
} else {
|
} else {
|
||||||
msgr.send(ChatColor.RED + "This command can only be executed by a player");
|
msgr.send(ChatColor.RED + "This command can only be executed by a player");
|
||||||
}
|
}
|
||||||
|
@ -1,999 +0,0 @@
|
|||||||
package me.jaimemartz.lobbybalancer.utils;
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
|
||||||
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
|
||||||
import net.md_5.bungee.config.Configuration;
|
|
||||||
import net.md_5.bungee.config.ConfigurationProvider;
|
|
||||||
import net.md_5.bungee.config.YamlConfiguration;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bStats collects some data for plugin authors.
|
|
||||||
*
|
|
||||||
* Check out https://bStats.org/ to learn more about bStats!
|
|
||||||
*/
|
|
||||||
public class Metrics {
|
|
||||||
|
|
||||||
// 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/bungeecord";
|
|
||||||
|
|
||||||
// The plugin
|
|
||||||
private final Plugin plugin;
|
|
||||||
|
|
||||||
// Is bStats enabled on this server?
|
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
// The uuid of the server
|
|
||||||
private String serverUUID;
|
|
||||||
|
|
||||||
// Should failed requests be logged?
|
|
||||||
private boolean logFailedRequests = false;
|
|
||||||
|
|
||||||
// A list with all known metrics class objects including this one
|
|
||||||
private static final List<Object> knownMetricsInstances = new ArrayList<>();
|
|
||||||
|
|
||||||
// A list with all custom charts
|
|
||||||
private final List<CustomChart> charts = new ArrayList<>();
|
|
||||||
|
|
||||||
public Metrics(Plugin plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
|
|
||||||
try {
|
|
||||||
loadConfig();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Failed to load configuration
|
|
||||||
plugin.getLogger().log(Level.WARNING, "Failed to load bStats config!", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are not allowed to send data about this server :(
|
|
||||||
if (!enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> usedMetricsClass = getFirstBStatsClass();
|
|
||||||
if (usedMetricsClass == null) {
|
|
||||||
// Failed to get first metrics class
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (usedMetricsClass == getClass()) {
|
|
||||||
// We are the first! :)
|
|
||||||
linkMetrics(this);
|
|
||||||
startSubmitting();
|
|
||||||
} else {
|
|
||||||
// We aren't the first so we link to the first metrics class
|
|
||||||
try {
|
|
||||||
usedMetricsClass.getMethod("linkMetrics", Object.class).invoke(null,this);
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
|
||||||
if (logFailedRequests) {
|
|
||||||
plugin.getLogger().log(Level.WARNING, "Failed to link to first metrics class " + usedMetricsClass.getName() + "!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a custom chart.
|
|
||||||
*
|
|
||||||
* @param chart The chart to add.
|
|
||||||
*/
|
|
||||||
public void addCustomChart(CustomChart chart) {
|
|
||||||
if (chart == null) {
|
|
||||||
plugin.getLogger().log(Level.WARNING, "Chart cannot be null");
|
|
||||||
}
|
|
||||||
charts.add(chart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Links an other metrics class with this class.
|
|
||||||
* This method is called using Reflection.
|
|
||||||
*
|
|
||||||
* @param metrics An object of the metrics class to link.
|
|
||||||
*/
|
|
||||||
public static void linkMetrics(Object metrics) {
|
|
||||||
knownMetricsInstances.add(metrics);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
data.addProperty("pluginVersion", pluginVersion);
|
|
||||||
|
|
||||||
JsonArray customCharts = new JsonArray();
|
|
||||||
for (CustomChart customChart : charts) {
|
|
||||||
// Add the data of the custom charts
|
|
||||||
JsonObject chart = customChart.getRequestJsonObject(plugin.getLogger(), logFailedRequests);
|
|
||||||
if (chart == null) { // If the chart is null, we skip it
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
customCharts.add(chart);
|
|
||||||
}
|
|
||||||
data.add("customCharts", customCharts);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startSubmitting() {
|
|
||||||
// We use a timer cause want to be independent from the server tps
|
|
||||||
final Timer timer = new Timer(true);
|
|
||||||
timer.scheduleAtFixedRate(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// The data collection (e.g. for custom graphs) is done sync
|
|
||||||
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
|
|
||||||
TaskScheduler scheduler = plugin.getProxy().getScheduler();
|
|
||||||
scheduler.schedule(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
submitData();
|
|
||||||
}
|
|
||||||
}, 0L, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
}, 1000*60*2, 1000*60*30);
|
|
||||||
// Submit the data every 30 minutes, first time after 2 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 server specific data.
|
|
||||||
*
|
|
||||||
* @return The server specific data.
|
|
||||||
*/
|
|
||||||
private JsonObject getServerData() {
|
|
||||||
// Minecraft specific data
|
|
||||||
int playerAmount = plugin.getProxy().getOnlineCount();
|
|
||||||
playerAmount = playerAmount > 500 ? 500 : playerAmount;
|
|
||||||
int onlineMode = plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0;
|
|
||||||
String bungeecordVersion = plugin.getProxy().getVersion();
|
|
||||||
int managedServers = plugin.getProxy().getServers().size();
|
|
||||||
|
|
||||||
// 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("managedServers", managedServers);
|
|
||||||
data.addProperty("onlineMode", onlineMode);
|
|
||||||
data.addProperty("bungeecordVersion", bungeecordVersion);
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
final JsonArray pluginData = new JsonArray();
|
|
||||||
// Search for all other bStats Metrics classes to get their plugin data
|
|
||||||
for (Object metrics : knownMetricsInstances) {
|
|
||||||
try {
|
|
||||||
Object plugin = metrics.getClass().getMethod("getPluginData").invoke(metrics);
|
|
||||||
if (plugin instanceof JsonObject) {
|
|
||||||
pluginData.add((JsonObject) plugin);
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
data.add("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(data);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Something went wrong! :(
|
|
||||||
if (logFailedRequests) {
|
|
||||||
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the bStats configuration.
|
|
||||||
*
|
|
||||||
* @throws IOException If something did not work :(
|
|
||||||
*/
|
|
||||||
private void loadConfig() throws IOException {
|
|
||||||
Path configPath = plugin.getDataFolder().toPath().getParent().resolve("bStats");
|
|
||||||
configPath.toFile().mkdirs();
|
|
||||||
File configFile = new File(configPath.toFile(), "config.yml");
|
|
||||||
if (!configFile.exists()) {
|
|
||||||
writeFile(configFile,
|
|
||||||
"#bStats collects some data for plugin authors like how many servers are using their plugins.",
|
|
||||||
"#To honor their work, you should not disable it.",
|
|
||||||
"#This has nearly no effect on the server performance!",
|
|
||||||
"#Check out https://bStats.org/ to learn more :)",
|
|
||||||
"enabled: true",
|
|
||||||
"serverUuid: \"" + UUID.randomUUID().toString() + "\"",
|
|
||||||
"logFailedRequests: false");
|
|
||||||
}
|
|
||||||
|
|
||||||
Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
|
|
||||||
|
|
||||||
// Load configuration
|
|
||||||
enabled = configuration.getBoolean("enabled", true);
|
|
||||||
serverUUID = configuration.getString("serverUuid");
|
|
||||||
logFailedRequests = configuration.getBoolean("logFailedRequests", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the first bStat Metrics class.
|
|
||||||
*
|
|
||||||
* @return The first bStats metrics class.
|
|
||||||
*/
|
|
||||||
private Class<?> getFirstBStatsClass() {
|
|
||||||
Path configPath = plugin.getDataFolder().toPath().getParent().resolve("bStats");
|
|
||||||
configPath.toFile().mkdirs();
|
|
||||||
File tempFile = new File(configPath.toFile(), "temp.txt");
|
|
||||||
|
|
||||||
try {
|
|
||||||
String className = readFile(tempFile);
|
|
||||||
if (className != null) {
|
|
||||||
try {
|
|
||||||
// Let's check if a class with the given name exists.
|
|
||||||
return Class.forName(className);
|
|
||||||
} catch (ClassNotFoundException ignored) { }
|
|
||||||
}
|
|
||||||
writeFile(tempFile, getClass().getName());
|
|
||||||
return getClass();
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (logFailedRequests) {
|
|
||||||
plugin.getLogger().log(Level.WARNING, "Failed to get first bStats class!", e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the first line of the file.
|
|
||||||
*
|
|
||||||
* @param file The file to read. Cannot be null.
|
|
||||||
* @return The first line of the file or <code>null</code> if the file does not exist or is empty.
|
|
||||||
* @throws IOException If something did not work :(
|
|
||||||
*/
|
|
||||||
private String readFile(File file) throws IOException {
|
|
||||||
if (!file.exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try (
|
|
||||||
FileReader fileReader = new FileReader(file);
|
|
||||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
|
||||||
) {
|
|
||||||
return bufferedReader.readLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a String to a file. It also adds a note for the user,
|
|
||||||
*
|
|
||||||
* @param file The file to write to. Cannot be null.
|
|
||||||
* @param lines The lines to write.
|
|
||||||
* @throws IOException If something did not work :(
|
|
||||||
*/
|
|
||||||
private void writeFile(File file, String... lines) throws IOException {
|
|
||||||
if (!file.exists()) {
|
|
||||||
file.createNewFile();
|
|
||||||
}
|
|
||||||
try (
|
|
||||||
FileWriter fileWriter = new FileWriter(file);
|
|
||||||
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)
|
|
||||||
) {
|
|
||||||
for (String line : lines) {
|
|
||||||
bufferedWriter.write(line);
|
|
||||||
bufferedWriter.newLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the data to the bStats server.
|
|
||||||
*
|
|
||||||
* @param data The data to send.
|
|
||||||
* @throws Exception If the request failed.
|
|
||||||
*/
|
|
||||||
private static void sendData(JsonObject data) throws Exception {
|
|
||||||
if (data == null) {
|
|
||||||
throw new IllegalArgumentException("Data cannot be null");
|
|
||||||
}
|
|
||||||
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();
|
|
||||||
|
|
||||||
connection.getInputStream().close(); // We don't care about the response - Just send our data :)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gzips the given String.
|
|
||||||
*
|
|
||||||
* @param str The string to gzip.
|
|
||||||
* @return The gzipped String.
|
|
||||||
* @throws IOException If the compression failed.
|
|
||||||
*/
|
|
||||||
private static byte[] compress(final String str) throws IOException {
|
|
||||||
if (str == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
|
||||||
gzip.write(str.getBytes("UTF-8"));
|
|
||||||
gzip.close();
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom chart.
|
|
||||||
*/
|
|
||||||
public static abstract class CustomChart {
|
|
||||||
|
|
||||||
// The id of the chart
|
|
||||||
protected final String chartId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public CustomChart(String chartId) {
|
|
||||||
if (chartId == null || chartId.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
|
||||||
}
|
|
||||||
this.chartId = chartId;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JsonObject getRequestJsonObject(Logger logger, boolean logFailedRequests) {
|
|
||||||
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) {
|
|
||||||
logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract JsonObject getChartData();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom simple pie.
|
|
||||||
*/
|
|
||||||
public static abstract class SimplePie extends CustomChart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public SimplePie(String chartId) {
|
|
||||||
super(chartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the pie.
|
|
||||||
*
|
|
||||||
* @return The value of the pie.
|
|
||||||
*/
|
|
||||||
public abstract String getValue();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsonObject getChartData() {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
String value = getValue();
|
|
||||||
if (value == null || value.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.addProperty("value", value);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom advanced pie.
|
|
||||||
*/
|
|
||||||
public static abstract class AdvancedPie extends CustomChart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public AdvancedPie(String chartId) {
|
|
||||||
super(chartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the values of the pie.
|
|
||||||
*
|
|
||||||
* @param valueMap Just an empty map. The only reason it exists is to make your life easier.
|
|
||||||
* You don't have to create a map yourself!
|
|
||||||
* @return The values of the pie.
|
|
||||||
*/
|
|
||||||
public abstract HashMap<String, Integer> getValues(HashMap<String, Integer> valueMap);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsonObject getChartData() {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
JsonObject values = new JsonObject();
|
|
||||||
HashMap<String, Integer> map = getValues(new HashMap<String, Integer>());
|
|
||||||
if (map == null || map.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean allSkipped = true;
|
|
||||||
for (Map.Entry<String, Integer> 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 single line chart.
|
|
||||||
*/
|
|
||||||
public static abstract class SingleLineChart extends CustomChart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public SingleLineChart(String chartId) {
|
|
||||||
super(chartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the chart.
|
|
||||||
*
|
|
||||||
* @return The value of the chart.
|
|
||||||
*/
|
|
||||||
public abstract int getValue();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsonObject getChartData() {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
int value = getValue();
|
|
||||||
if (value == 0) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.addProperty("value", value);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom multi line chart.
|
|
||||||
*/
|
|
||||||
public static abstract class MultiLineChart extends CustomChart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public MultiLineChart(String chartId) {
|
|
||||||
super(chartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the values of the chart.
|
|
||||||
*
|
|
||||||
* @param valueMap Just an empty map. The only reason it exists is to make your life easier.
|
|
||||||
* You don't have to create a map yourself!
|
|
||||||
* @return The values of the chart.
|
|
||||||
*/
|
|
||||||
public abstract HashMap<String, Integer> getValues(HashMap<String, Integer> valueMap);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsonObject getChartData() {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
JsonObject values = new JsonObject();
|
|
||||||
HashMap<String, Integer> map = getValues(new HashMap<String, Integer>());
|
|
||||||
if (map == null || map.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean allSkipped = true;
|
|
||||||
for (Map.Entry<String, Integer> 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 map chart.
|
|
||||||
*/
|
|
||||||
public static abstract class SimpleMapChart extends CustomChart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public SimpleMapChart(String chartId) {
|
|
||||||
super(chartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the chart.
|
|
||||||
*
|
|
||||||
* @return The value of the chart.
|
|
||||||
*/
|
|
||||||
public abstract Country getValue();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsonObject getChartData() {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
Country value = getValue();
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.addProperty("value", value.getCountryIsoTag());
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom advanced map chart.
|
|
||||||
*/
|
|
||||||
public static abstract class AdvancedMapChart extends CustomChart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
public AdvancedMapChart(String chartId) {
|
|
||||||
super(chartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the chart.
|
|
||||||
*
|
|
||||||
* @param valueMap Just an empty map. The only reason it exists is to make your life easier.
|
|
||||||
* You don't have to create a map yourself!
|
|
||||||
* @return The value of the chart.
|
|
||||||
*/
|
|
||||||
public abstract HashMap<Country, Integer> getValues(HashMap<Country, Integer> valueMap);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsonObject getChartData() {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
JsonObject values = new JsonObject();
|
|
||||||
HashMap<Country, Integer> map = getValues(new HashMap<Country, Integer>());
|
|
||||||
if (map == null || map.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean allSkipped = true;
|
|
||||||
for (Map.Entry<Country, Integer> entry : map.entrySet()) {
|
|
||||||
if (entry.getValue() == 0) {
|
|
||||||
continue; // Skip this invalid
|
|
||||||
}
|
|
||||||
allSkipped = false;
|
|
||||||
values.addProperty(entry.getKey().getCountryIsoTag(), entry.getValue());
|
|
||||||
}
|
|
||||||
if (allSkipped) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.add("values", values);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A enum which is used for custom maps.
|
|
||||||
*/
|
|
||||||
public enum Country {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bStats will use the country of the server.
|
|
||||||
*/
|
|
||||||
AUTO_DETECT("AUTO", "Auto Detected"),
|
|
||||||
|
|
||||||
ANDORRA("AD", "Andorra"),
|
|
||||||
UNITED_ARAB_EMIRATES("AE", "United Arab Emirates"),
|
|
||||||
AFGHANISTAN("AF", "Afghanistan"),
|
|
||||||
ANTIGUA_AND_BARBUDA("AG", "Antigua and Barbuda"),
|
|
||||||
ANGUILLA("AI", "Anguilla"),
|
|
||||||
ALBANIA("AL", "Albania"),
|
|
||||||
ARMENIA("AM", "Armenia"),
|
|
||||||
NETHERLANDS_ANTILLES("AN", "Netherlands Antilles"),
|
|
||||||
ANGOLA("AO", "Angola"),
|
|
||||||
ANTARCTICA("AQ", "Antarctica"),
|
|
||||||
ARGENTINA("AR", "Argentina"),
|
|
||||||
AMERICAN_SAMOA("AS", "American Samoa"),
|
|
||||||
AUSTRIA("AT", "Austria"),
|
|
||||||
AUSTRALIA("AU", "Australia"),
|
|
||||||
ARUBA("AW", "Aruba"),
|
|
||||||
ÅLAND_ISLANDS("AX", "Åland Islands"),
|
|
||||||
AZERBAIJAN("AZ", "Azerbaijan"),
|
|
||||||
BOSNIA_AND_HERZEGOVINA("BA", "Bosnia and Herzegovina"),
|
|
||||||
BARBADOS("BB", "Barbados"),
|
|
||||||
BANGLADESH("BD", "Bangladesh"),
|
|
||||||
BELGIUM("BE", "Belgium"),
|
|
||||||
BURKINA_FASO("BF", "Burkina Faso"),
|
|
||||||
BULGARIA("BG", "Bulgaria"),
|
|
||||||
BAHRAIN("BH", "Bahrain"),
|
|
||||||
BURUNDI("BI", "Burundi"),
|
|
||||||
BENIN("BJ", "Benin"),
|
|
||||||
SAINT_BARTHÉLEMY("BL", "Saint Barthélemy"),
|
|
||||||
BERMUDA("BM", "Bermuda"),
|
|
||||||
BRUNEI("BN", "Brunei"),
|
|
||||||
BOLIVIA("BO", "Bolivia"),
|
|
||||||
BONAIRE_SINT_EUSTATIUS_AND_SABA("BQ", "Bonaire, Sint Eustatius and Saba"),
|
|
||||||
BRAZIL("BR", "Brazil"),
|
|
||||||
BAHAMAS("BS", "Bahamas"),
|
|
||||||
BHUTAN("BT", "Bhutan"),
|
|
||||||
BOUVET_ISLAND("BV", "Bouvet Island"),
|
|
||||||
BOTSWANA("BW", "Botswana"),
|
|
||||||
BELARUS("BY", "Belarus"),
|
|
||||||
BELIZE("BZ", "Belize"),
|
|
||||||
CANADA("CA", "Canada"),
|
|
||||||
COCOS_ISLANDS("CC", "Cocos Islands"),
|
|
||||||
THE_DEMOCRATIC_REPUBLIC_OF_CONGO("CD", "The Democratic Republic Of Congo"),
|
|
||||||
CENTRAL_AFRICAN_REPUBLIC("CF", "Central African Republic"),
|
|
||||||
CONGO("CG", "Congo"),
|
|
||||||
SWITZERLAND("CH", "Switzerland"),
|
|
||||||
CÔTE_D_IVOIRE("CI", "Côte d'Ivoire"),
|
|
||||||
COOK_ISLANDS("CK", "Cook Islands"),
|
|
||||||
CHILE("CL", "Chile"),
|
|
||||||
CAMEROON("CM", "Cameroon"),
|
|
||||||
CHINA("CN", "China"),
|
|
||||||
COLOMBIA("CO", "Colombia"),
|
|
||||||
COSTA_RICA("CR", "Costa Rica"),
|
|
||||||
CUBA("CU", "Cuba"),
|
|
||||||
CAPE_VERDE("CV", "Cape Verde"),
|
|
||||||
CURAÇAO("CW", "Curaçao"),
|
|
||||||
CHRISTMAS_ISLAND("CX", "Christmas Island"),
|
|
||||||
CYPRUS("CY", "Cyprus"),
|
|
||||||
CZECH_REPUBLIC("CZ", "Czech Republic"),
|
|
||||||
GERMANY("DE", "Germany"),
|
|
||||||
DJIBOUTI("DJ", "Djibouti"),
|
|
||||||
DENMARK("DK", "Denmark"),
|
|
||||||
DOMINICA("DM", "Dominica"),
|
|
||||||
DOMINICAN_REPUBLIC("DO", "Dominican Republic"),
|
|
||||||
ALGERIA("DZ", "Algeria"),
|
|
||||||
ECUADOR("EC", "Ecuador"),
|
|
||||||
ESTONIA("EE", "Estonia"),
|
|
||||||
EGYPT("EG", "Egypt"),
|
|
||||||
WESTERN_SAHARA("EH", "Western Sahara"),
|
|
||||||
ERITREA("ER", "Eritrea"),
|
|
||||||
SPAIN("ES", "Spain"),
|
|
||||||
ETHIOPIA("ET", "Ethiopia"),
|
|
||||||
FINLAND("FI", "Finland"),
|
|
||||||
FIJI("FJ", "Fiji"),
|
|
||||||
FALKLAND_ISLANDS("FK", "Falkland Islands"),
|
|
||||||
MICRONESIA("FM", "Micronesia"),
|
|
||||||
FAROE_ISLANDS("FO", "Faroe Islands"),
|
|
||||||
FRANCE("FR", "France"),
|
|
||||||
GABON("GA", "Gabon"),
|
|
||||||
UNITED_KINGDOM("GB", "United Kingdom"),
|
|
||||||
GRENADA("GD", "Grenada"),
|
|
||||||
GEORGIA("GE", "Georgia"),
|
|
||||||
FRENCH_GUIANA("GF", "French Guiana"),
|
|
||||||
GUERNSEY("GG", "Guernsey"),
|
|
||||||
GHANA("GH", "Ghana"),
|
|
||||||
GIBRALTAR("GI", "Gibraltar"),
|
|
||||||
GREENLAND("GL", "Greenland"),
|
|
||||||
GAMBIA("GM", "Gambia"),
|
|
||||||
GUINEA("GN", "Guinea"),
|
|
||||||
GUADELOUPE("GP", "Guadeloupe"),
|
|
||||||
EQUATORIAL_GUINEA("GQ", "Equatorial Guinea"),
|
|
||||||
GREECE("GR", "Greece"),
|
|
||||||
SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS("GS", "South Georgia And The South Sandwich Islands"),
|
|
||||||
GUATEMALA("GT", "Guatemala"),
|
|
||||||
GUAM("GU", "Guam"),
|
|
||||||
GUINEA_BISSAU("GW", "Guinea-Bissau"),
|
|
||||||
GUYANA("GY", "Guyana"),
|
|
||||||
HONG_KONG("HK", "Hong Kong"),
|
|
||||||
HEARD_ISLAND_AND_MCDONALD_ISLANDS("HM", "Heard Island And McDonald Islands"),
|
|
||||||
HONDURAS("HN", "Honduras"),
|
|
||||||
CROATIA("HR", "Croatia"),
|
|
||||||
HAITI("HT", "Haiti"),
|
|
||||||
HUNGARY("HU", "Hungary"),
|
|
||||||
INDONESIA("ID", "Indonesia"),
|
|
||||||
IRELAND("IE", "Ireland"),
|
|
||||||
ISRAEL("IL", "Israel"),
|
|
||||||
ISLE_OF_MAN("IM", "Isle Of Man"),
|
|
||||||
INDIA("IN", "India"),
|
|
||||||
BRITISH_INDIAN_OCEAN_TERRITORY("IO", "British Indian Ocean Territory"),
|
|
||||||
IRAQ("IQ", "Iraq"),
|
|
||||||
IRAN("IR", "Iran"),
|
|
||||||
ICELAND("IS", "Iceland"),
|
|
||||||
ITALY("IT", "Italy"),
|
|
||||||
JERSEY("JE", "Jersey"),
|
|
||||||
JAMAICA("JM", "Jamaica"),
|
|
||||||
JORDAN("JO", "Jordan"),
|
|
||||||
JAPAN("JP", "Japan"),
|
|
||||||
KENYA("KE", "Kenya"),
|
|
||||||
KYRGYZSTAN("KG", "Kyrgyzstan"),
|
|
||||||
CAMBODIA("KH", "Cambodia"),
|
|
||||||
KIRIBATI("KI", "Kiribati"),
|
|
||||||
COMOROS("KM", "Comoros"),
|
|
||||||
SAINT_KITTS_AND_NEVIS("KN", "Saint Kitts And Nevis"),
|
|
||||||
NORTH_KOREA("KP", "North Korea"),
|
|
||||||
SOUTH_KOREA("KR", "South Korea"),
|
|
||||||
KUWAIT("KW", "Kuwait"),
|
|
||||||
CAYMAN_ISLANDS("KY", "Cayman Islands"),
|
|
||||||
KAZAKHSTAN("KZ", "Kazakhstan"),
|
|
||||||
LAOS("LA", "Laos"),
|
|
||||||
LEBANON("LB", "Lebanon"),
|
|
||||||
SAINT_LUCIA("LC", "Saint Lucia"),
|
|
||||||
LIECHTENSTEIN("LI", "Liechtenstein"),
|
|
||||||
SRI_LANKA("LK", "Sri Lanka"),
|
|
||||||
LIBERIA("LR", "Liberia"),
|
|
||||||
LESOTHO("LS", "Lesotho"),
|
|
||||||
LITHUANIA("LT", "Lithuania"),
|
|
||||||
LUXEMBOURG("LU", "Luxembourg"),
|
|
||||||
LATVIA("LV", "Latvia"),
|
|
||||||
LIBYA("LY", "Libya"),
|
|
||||||
MOROCCO("MA", "Morocco"),
|
|
||||||
MONACO("MC", "Monaco"),
|
|
||||||
MOLDOVA("MD", "Moldova"),
|
|
||||||
MONTENEGRO("ME", "Montenegro"),
|
|
||||||
SAINT_MARTIN("MF", "Saint Martin"),
|
|
||||||
MADAGASCAR("MG", "Madagascar"),
|
|
||||||
MARSHALL_ISLANDS("MH", "Marshall Islands"),
|
|
||||||
MACEDONIA("MK", "Macedonia"),
|
|
||||||
MALI("ML", "Mali"),
|
|
||||||
MYANMAR("MM", "Myanmar"),
|
|
||||||
MONGOLIA("MN", "Mongolia"),
|
|
||||||
MACAO("MO", "Macao"),
|
|
||||||
NORTHERN_MARIANA_ISLANDS("MP", "Northern Mariana Islands"),
|
|
||||||
MARTINIQUE("MQ", "Martinique"),
|
|
||||||
MAURITANIA("MR", "Mauritania"),
|
|
||||||
MONTSERRAT("MS", "Montserrat"),
|
|
||||||
MALTA("MT", "Malta"),
|
|
||||||
MAURITIUS("MU", "Mauritius"),
|
|
||||||
MALDIVES("MV", "Maldives"),
|
|
||||||
MALAWI("MW", "Malawi"),
|
|
||||||
MEXICO("MX", "Mexico"),
|
|
||||||
MALAYSIA("MY", "Malaysia"),
|
|
||||||
MOZAMBIQUE("MZ", "Mozambique"),
|
|
||||||
NAMIBIA("NA", "Namibia"),
|
|
||||||
NEW_CALEDONIA("NC", "New Caledonia"),
|
|
||||||
NIGER("NE", "Niger"),
|
|
||||||
NORFOLK_ISLAND("NF", "Norfolk Island"),
|
|
||||||
NIGERIA("NG", "Nigeria"),
|
|
||||||
NICARAGUA("NI", "Nicaragua"),
|
|
||||||
NETHERLANDS("NL", "Netherlands"),
|
|
||||||
NORWAY("NO", "Norway"),
|
|
||||||
NEPAL("NP", "Nepal"),
|
|
||||||
NAURU("NR", "Nauru"),
|
|
||||||
NIUE("NU", "Niue"),
|
|
||||||
NEW_ZEALAND("NZ", "New Zealand"),
|
|
||||||
OMAN("OM", "Oman"),
|
|
||||||
PANAMA("PA", "Panama"),
|
|
||||||
PERU("PE", "Peru"),
|
|
||||||
FRENCH_POLYNESIA("PF", "French Polynesia"),
|
|
||||||
PAPUA_NEW_GUINEA("PG", "Papua New Guinea"),
|
|
||||||
PHILIPPINES("PH", "Philippines"),
|
|
||||||
PAKISTAN("PK", "Pakistan"),
|
|
||||||
POLAND("PL", "Poland"),
|
|
||||||
SAINT_PIERRE_AND_MIQUELON("PM", "Saint Pierre And Miquelon"),
|
|
||||||
PITCAIRN("PN", "Pitcairn"),
|
|
||||||
PUERTO_RICO("PR", "Puerto Rico"),
|
|
||||||
PALESTINE("PS", "Palestine"),
|
|
||||||
PORTUGAL("PT", "Portugal"),
|
|
||||||
PALAU("PW", "Palau"),
|
|
||||||
PARAGUAY("PY", "Paraguay"),
|
|
||||||
QATAR("QA", "Qatar"),
|
|
||||||
REUNION("RE", "Reunion"),
|
|
||||||
ROMANIA("RO", "Romania"),
|
|
||||||
SERBIA("RS", "Serbia"),
|
|
||||||
RUSSIA("RU", "Russia"),
|
|
||||||
RWANDA("RW", "Rwanda"),
|
|
||||||
SAUDI_ARABIA("SA", "Saudi Arabia"),
|
|
||||||
SOLOMON_ISLANDS("SB", "Solomon Islands"),
|
|
||||||
SEYCHELLES("SC", "Seychelles"),
|
|
||||||
SUDAN("SD", "Sudan"),
|
|
||||||
SWEDEN("SE", "Sweden"),
|
|
||||||
SINGAPORE("SG", "Singapore"),
|
|
||||||
SAINT_HELENA("SH", "Saint Helena"),
|
|
||||||
SLOVENIA("SI", "Slovenia"),
|
|
||||||
SVALBARD_AND_JAN_MAYEN("SJ", "Svalbard And Jan Mayen"),
|
|
||||||
SLOVAKIA("SK", "Slovakia"),
|
|
||||||
SIERRA_LEONE("SL", "Sierra Leone"),
|
|
||||||
SAN_MARINO("SM", "San Marino"),
|
|
||||||
SENEGAL("SN", "Senegal"),
|
|
||||||
SOMALIA("SO", "Somalia"),
|
|
||||||
SURINAME("SR", "Suriname"),
|
|
||||||
SOUTH_SUDAN("SS", "South Sudan"),
|
|
||||||
SAO_TOME_AND_PRINCIPE("ST", "Sao Tome And Principe"),
|
|
||||||
EL_SALVADOR("SV", "El Salvador"),
|
|
||||||
SINT_MAARTEN_DUTCH_PART("SX", "Sint Maarten (Dutch part)"),
|
|
||||||
SYRIA("SY", "Syria"),
|
|
||||||
SWAZILAND("SZ", "Swaziland"),
|
|
||||||
TURKS_AND_CAICOS_ISLANDS("TC", "Turks And Caicos Islands"),
|
|
||||||
CHAD("TD", "Chad"),
|
|
||||||
FRENCH_SOUTHERN_TERRITORIES("TF", "French Southern Territories"),
|
|
||||||
TOGO("TG", "Togo"),
|
|
||||||
THAILAND("TH", "Thailand"),
|
|
||||||
TAJIKISTAN("TJ", "Tajikistan"),
|
|
||||||
TOKELAU("TK", "Tokelau"),
|
|
||||||
TIMOR_LESTE("TL", "Timor-Leste"),
|
|
||||||
TURKMENISTAN("TM", "Turkmenistan"),
|
|
||||||
TUNISIA("TN", "Tunisia"),
|
|
||||||
TONGA("TO", "Tonga"),
|
|
||||||
TURKEY("TR", "Turkey"),
|
|
||||||
TRINIDAD_AND_TOBAGO("TT", "Trinidad and Tobago"),
|
|
||||||
TUVALU("TV", "Tuvalu"),
|
|
||||||
TAIWAN("TW", "Taiwan"),
|
|
||||||
TANZANIA("TZ", "Tanzania"),
|
|
||||||
UKRAINE("UA", "Ukraine"),
|
|
||||||
UGANDA("UG", "Uganda"),
|
|
||||||
UNITED_STATES_MINOR_OUTLYING_ISLANDS("UM", "United States Minor Outlying Islands"),
|
|
||||||
UNITED_STATES("US", "United States"),
|
|
||||||
URUGUAY("UY", "Uruguay"),
|
|
||||||
UZBEKISTAN("UZ", "Uzbekistan"),
|
|
||||||
VATICAN("VA", "Vatican"),
|
|
||||||
SAINT_VINCENT_AND_THE_GRENADINES("VC", "Saint Vincent And The Grenadines"),
|
|
||||||
VENEZUELA("VE", "Venezuela"),
|
|
||||||
BRITISH_VIRGIN_ISLANDS("VG", "British Virgin Islands"),
|
|
||||||
U_S__VIRGIN_ISLANDS("VI", "U.S. Virgin Islands"),
|
|
||||||
VIETNAM("VN", "Vietnam"),
|
|
||||||
VANUATU("VU", "Vanuatu"),
|
|
||||||
WALLIS_AND_FUTUNA("WF", "Wallis And Futuna"),
|
|
||||||
SAMOA("WS", "Samoa"),
|
|
||||||
YEMEN("YE", "Yemen"),
|
|
||||||
MAYOTTE("YT", "Mayotte"),
|
|
||||||
SOUTH_AFRICA("ZA", "South Africa"),
|
|
||||||
ZAMBIA("ZM", "Zambia"),
|
|
||||||
ZIMBABWE("ZW", "Zimbabwe");
|
|
||||||
|
|
||||||
private String isoTag;
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
Country(String isoTag, String name) {
|
|
||||||
this.isoTag = isoTag;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the name of the country.
|
|
||||||
*
|
|
||||||
* @return The name of the country.
|
|
||||||
*/
|
|
||||||
public String getCountryName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the iso tag of the country.
|
|
||||||
*
|
|
||||||
* @return The iso tag of the country.
|
|
||||||
*/
|
|
||||||
public String getCountryIsoTag() {
|
|
||||||
return isoTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a country by it's iso tag.
|
|
||||||
*
|
|
||||||
* @param isoTag The iso tag of the county.
|
|
||||||
* @return The country with the given iso tag or <code>null</code> if unknown.
|
|
||||||
*/
|
|
||||||
public static Country byIsoTag(String isoTag) {
|
|
||||||
for (Country country : Country.values()) {
|
|
||||||
if (country.getCountryIsoTag().equals(isoTag)) {
|
|
||||||
return country;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a country by a locale.
|
|
||||||
*
|
|
||||||
* @param locale The locale.
|
|
||||||
* @return The country from the giben locale or <code>null</code> if unknown country or
|
|
||||||
* if the locale does not contain a country.
|
|
||||||
*/
|
|
||||||
public static Country byLocale(Locale locale) {
|
|
||||||
return byIsoTag(locale.getCountry());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -14,9 +14,6 @@ settings:
|
|||||||
# Whether the plugin should ask you to update or not
|
# Whether the plugin should ask you to update or not
|
||||||
check-updates: true
|
check-updates: true
|
||||||
|
|
||||||
# Disable this to opt-out of the plugin sending stats
|
|
||||||
submit-stats: true
|
|
||||||
|
|
||||||
# Pings to the servers to see if they can be accessed or not
|
# Pings to the servers to see if they can be accessed or not
|
||||||
server-check:
|
server-check:
|
||||||
# If this is disabled the players will connect to the first server available
|
# If this is disabled the players will connect to the first server available
|
||||||
|
Loading…
Reference in New Issue
Block a user