From b59c53c2e69e20cd9e444b1dfd2b13d6af6cd70b Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Thu, 16 Jul 2020 19:55:16 +0100 Subject: [PATCH 01/16] Fix long outstanding prefix bug --- src/main/resources/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3ff862a3d..a49e2e941 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -6,7 +6,7 @@ options: auto-update: true backwards-compatibility: true - chat-prefix: '&a&lSlimefun 4 &7>' + chat-prefix: '&a&lSlimefun 4&7> ' armor-update-interval: 10 enable-armor-effects: true auto-save-delay-in-minutes: 10 From 67db0ce59e7ca847e2b5bc2aa148458e5850e245 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:15:21 +0100 Subject: [PATCH 02/16] Oh baby, this is a big one --- pom.xml | 21 +- .../commands/subcommands/VersionsCommand.java | 17 +- .../github/ContributionsConnector.java | 21 +- .../core/services/github/GitHubConnector.java | 83 +++----- .../services/github/GitHubIssuesTracker.java | 15 +- .../core/services/github/GitHubService.java | 12 +- .../core/services/metrics/AddonsChart.java | 27 --- .../services/metrics/AutoUpdaterChart.java | 16 -- .../core/services/metrics/CommandChart.java | 25 --- .../metrics/CompatibilityModeChart.java | 16 -- .../services/metrics/GuideLayoutChart.java | 17 -- .../core/services/metrics/MetricsService.java | 188 +++++++++++++++--- .../services/metrics/PlayerLanguageChart.java | 31 --- .../metrics/ResearchesEnabledChart.java | 16 -- .../services/metrics/ResourcePackChart.java | 25 --- .../services/metrics/ServerLanguageChart.java | 18 -- .../services/metrics/ServerSizeChart.java | 40 ---- .../metrics/SlimefunVersionChart.java | 24 --- .../implementation/SlimefunPlugin.java | 14 +- src/main/resources/config.yml | 3 + 20 files changed, 250 insertions(+), 379 deletions(-) delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AddonsChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AutoUpdaterChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CommandChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CompatibilityModeChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/GuideLayoutChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/PlayerLanguageChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResearchesEnabledChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResourcePackChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerLanguageChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerSizeChart.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/SlimefunVersionChart.java diff --git a/pom.xml b/pom.xml index 5d7ef12a5..80136ff3f 100644 --- a/pom.xml +++ b/pom.xml @@ -161,10 +161,6 @@ - - org.bstats - me.mrCookieSlime.Slimefun.bstats - io.github.thebusybiscuit.cscorelib2 me.mrCookieSlime.Slimefun.cscorelib2 @@ -310,10 +306,19 @@ compile - org.bstats - bstats-bukkit - 1.7 - compile + com.konghq + unirest-java + 3.8.06 + + + com.google.code.gson + gson + + + org.apache.httpcomponents + httpasyncclient + + diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java index 386d7ccbc..1b533925b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java @@ -2,17 +2,16 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands; import java.util.Collection; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.plugin.Plugin; - import io.github.thebusybiscuit.cscorelib2.chat.ChatColors; import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils; import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand; import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.plugin.Plugin; class VersionsCommand extends SubCommand { @@ -36,7 +35,11 @@ class VersionsCommand extends SubCommand { sender.sendMessage(ChatColors.color("&a" + Bukkit.getName() + " &2" + ReflectionUtils.getVersion())); sender.sendMessage(""); sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion())); - sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion())); + sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()) + + (SlimefunPlugin.getMetricsService().getVersion() != null + ? " (Metrics build: #" + SlimefunPlugin.getMetricsService().getVersion() + ')' + : "") + ); if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) { sender.sendMessage(ChatColor.YELLOW + "Backwards compatiblity enabled!"); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java index 5f50d2783..3bbe92b1b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java @@ -10,6 +10,9 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import kong.unirest.JsonNode; +import kong.unirest.json.JSONArray; +import kong.unirest.json.JSONObject; import me.mrCookieSlime.Slimefun.api.Slimefun; class ContributionsConnector extends GitHubConnector { @@ -57,10 +60,10 @@ class ContributionsConnector extends GitHubConnector { } @Override - public void onSuccess(JsonElement element) { + public void onSuccess(JsonNode element) { finished = true; - if (element.isJsonArray()) { - computeContributors(element.getAsJsonArray()); + if (element.isArray()) { + computeContributors(element.getArray()); } else { Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", element); @@ -82,13 +85,13 @@ class ContributionsConnector extends GitHubConnector { return "/contributors?per_page=100&page=" + page; } - private void computeContributors(JsonArray array) { - for (int i = 0; i < array.size(); i++) { - JsonObject object = array.get(i).getAsJsonObject(); + private void computeContributors(JSONArray array) { + for (int i = 0; i < array.length(); i++) { + JSONObject object = array.getJSONObject(i); - String name = object.get("login").getAsString(); - int commits = object.get("contributions").getAsInt(); - String profile = object.get("html_url").getAsString(); + String name = object.getString("login"); + int commits = object.getInt("contributions"); + String profile = object.getString("html_url"); if (!blacklist.contains(name)) { github.addContributor(aliases.getOrDefault(name, name), profile, role, commits); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java index 68e76ec42..90bfbc767 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java @@ -1,22 +1,15 @@ package io.github.thebusybiscuit.slimefun4.core.services.github; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; import java.nio.charset.StandardCharsets; import java.util.logging.Level; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import kong.unirest.HttpResponse; +import kong.unirest.JsonNode; +import kong.unirest.Unirest; +import kong.unirest.UnirestException; import me.mrCookieSlime.Slimefun.api.Slimefun; abstract class GitHubConnector { @@ -34,7 +27,7 @@ abstract class GitHubConnector { public abstract String getURLSuffix(); - public abstract void onSuccess(JsonElement element); + public abstract void onSuccess(JsonNode element); public void onFailure() { // Don't do anything by default @@ -48,58 +41,30 @@ abstract class GitHubConnector { } try { - URL website = new URL("https://api.github.com/repos/" + repository + getURLSuffix()); + HttpResponse resp = Unirest + .get("https://api.github.com/repos/" + repository + getURLSuffix()) + .header("User-Agent", "Slimefun4 (https://github.com/Slimefun)") + .asJson(); - URLConnection connection = website.openConnection(); - connection.setConnectTimeout(8000); - connection.addRequestProperty("Accept-Charset", "UTF-8"); - connection.addRequestProperty("User-Agent", "Slimefun 4 GitHub Agent (by TheBusyBiscuit)"); - connection.setDoOutput(true); - - try (ReadableByteChannel channel = Channels.newChannel(connection.getInputStream())) { - try (FileOutputStream stream = new FileOutputStream(file)) { - stream.getChannel().transferFrom(channel, 0, Long.MAX_VALUE); - parseData(); - } - } - } - catch (IOException e) { + if (resp.isSuccess()) { + onSuccess(resp.getBody()); + writeCacheFile(resp.getBody()); + } else + Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}", + repository + getURLSuffix()); + } catch (UnirestException e) { if (github.isLoggingEnabled()) { Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time."); } - - if (hasData()) { - parseData(); - } - else { - onFailure(); - } - } - } - - public boolean hasData() { - return getFile().exists(); - } - - public File getFile() { - return file; - } - - public void parseData() { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(getFile()), StandardCharsets.UTF_8))) { - StringBuilder builder = new StringBuilder(); - - String line; - while ((line = reader.readLine()) != null) { - builder.append(line); - } - - JsonElement element = new JsonParser().parse(builder.toString()); - onSuccess(element); - } - catch (IOException x) { - Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while parsing GitHub-Data for Slimefun " + SlimefunPlugin.getVersion()); onFailure(); } } + + private void writeCacheFile(JsonNode node) { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(node.toString().getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache"); + } + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java index 9686d4e92..eb187dd37 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java @@ -6,6 +6,10 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import kong.unirest.JsonNode; +import kong.unirest.json.JSONArray; +import kong.unirest.json.JSONElement; +import kong.unirest.json.JSONObject; import me.mrCookieSlime.Slimefun.api.Slimefun; class GitHubIssuesTracker extends GitHubConnector { @@ -25,15 +29,16 @@ class GitHubIssuesTracker extends GitHubConnector { } @Override - public void onSuccess(JsonElement element) { - if (element.isJsonArray()) { - JsonArray array = element.getAsJsonArray(); + public void onSuccess(JsonNode element) { + if (element.isArray()) { + JSONArray array = element.getArray(); int issues = 0; int pullRequests = 0; - for (JsonElement elem : array) { - JsonObject obj = elem.getAsJsonObject(); + // Don't even question why this is an Iterable + for (Object elem : array) { + JSONObject obj = ((JsonNode) elem).getObject(); if (obj.has("pull_request")) { pullRequests++; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java index 1942eeb52..c9f5ca8e7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java @@ -17,6 +17,8 @@ import io.github.thebusybiscuit.slimefun4.core.services.localization.Translators import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; import io.github.thebusybiscuit.slimefun4.utils.NumberUtils; +import kong.unirest.JsonNode; +import kong.unirest.json.JSONObject; /** * This Service is responsible for grabbing every {@link Contributor} to this project @@ -108,11 +110,11 @@ public class GitHubService { connectors.add(new GitHubConnector(this, repository) { @Override - public void onSuccess(JsonElement element) { - JsonObject object = element.getAsJsonObject(); - forks = object.get("forks").getAsInt(); - stars = object.get("stargazers_count").getAsInt(); - lastUpdate = NumberUtils.parseGitHubDate(object.get("pushed_at").getAsString()); + public void onSuccess(JsonNode element) { + JSONObject object = element.getObject(); + forks = object.getInt("forks"); + stars = object.getInt("stargazers_count"); + lastUpdate = NumberUtils.parseGitHubDate(object.getString("pushed_at")); } @Override diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AddonsChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AddonsChart.java deleted file mode 100644 index 2ed2a7d59..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AddonsChart.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import java.util.HashMap; -import java.util.Map; - -import org.bstats.bukkit.Metrics.AdvancedPie; -import org.bukkit.plugin.Plugin; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class AddonsChart extends AdvancedPie { - - AddonsChart() { - super("installed_addons", () -> { - Map addons = new HashMap<>(); - - for (Plugin plugin : SlimefunPlugin.getInstalledAddons()) { - if (plugin.isEnabled()) { - addons.put(plugin.getName(), 1); - } - } - - return addons; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AutoUpdaterChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AutoUpdaterChart.java deleted file mode 100644 index eba426338..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/AutoUpdaterChart.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class AutoUpdaterChart extends SimplePie { - - AutoUpdaterChart() { - super("auto_updates", () -> { - boolean enabled = SlimefunPlugin.getUpdater().isEnabled(); - return enabled ? "enabled" : "disabled"; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CommandChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CommandChart.java deleted file mode 100644 index d9fc909c1..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CommandChart.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import java.util.HashMap; -import java.util.Map; - -import org.bstats.bukkit.Metrics.AdvancedPie; - -import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class CommandChart extends AdvancedPie { - - CommandChart() { - super("commands_ran", () -> { - Map commands = new HashMap<>(); - - for (Map.Entry entry : SlimefunPlugin.getCommand().getCommandUsage().entrySet()) { - commands.put("/sf " + entry.getKey().getName(), entry.getValue()); - } - - return commands; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CompatibilityModeChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CompatibilityModeChart.java deleted file mode 100644 index 045c2657e..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/CompatibilityModeChart.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class CompatibilityModeChart extends SimplePie { - - CompatibilityModeChart() { - super("compatibility_mode", () -> { - boolean enabled = SlimefunPlugin.getRegistry().isBackwardsCompatible(); - return enabled ? "enabled" : "disabled"; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/GuideLayoutChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/GuideLayoutChart.java deleted file mode 100644 index 75fc72b42..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/GuideLayoutChart.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class GuideLayoutChart extends SimplePie { - - GuideLayoutChart() { - super("guide_layout", () -> { - boolean book = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book"); - - return book ? "Book" : "Chest GUI"; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java index d6654f6a2..c1f1d6c9d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java @@ -1,55 +1,183 @@ package io.github.thebusybiscuit.slimefun4.core.services.metrics; -import org.bstats.bukkit.Metrics; -import org.bukkit.plugin.Plugin; +import javax.annotation.Nullable; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import kong.unirest.HttpResponse; +import kong.unirest.JsonNode; +import kong.unirest.Unirest; +import kong.unirest.UnirestException; +import me.mrCookieSlime.Slimefun.api.Slimefun; +import org.bukkit.plugin.Plugin; /** * This Class represents a Metrics Service that sends data to https://bstats.org/ * This data is used to analyse the usage of this {@link Plugin}. - * - * You can find more info in the README file of this Project on GitHub. - * - * @author TheBusyBiscuit + *

+ * You can find more info in the README file of this Project on GitHub.
+ * Note: To start the metrics you will need to be calling {@link #start()} * + * @author TheBusyBiscuit */ public class MetricsService { - private final SlimefunPlugin plugin; + private static final String REPO_NAME = "MetricsModule"; + private static final String GH_API = "https://api.github.com/repos/Slimefun/" + REPO_NAME; + private static final String GH_REPO_RELEASES = "https://github.com/Slimefun/" + REPO_NAME + + "/releases/download"; + + private final SlimefunPlugin plugin; + private final File metricFile; + + private URLClassLoader moduleClassLoader; + private String metricVersion = null; + + static { + Unirest.config() + .concurrency(2, 1) + .setDefaultHeader("User-Agent", "MetricsModule Auto-Updater") + .setDefaultHeader("Accept", "application/vnd.github.v3+json") + .enableCookieManagement(false) + .cookieSpec("ignoreCookies"); + } - /** - * This creates a new {@link MetricsService}. The constructor does not set up - * anything related to bStats yet, that happens in the {@link MetricsService#start()} method. - * - * @param plugin - * The instance of our {@link SlimefunPlugin} - */ public MetricsService(SlimefunPlugin plugin) { this.plugin = plugin; + this.metricFile = new File(plugin.getDataFolder(), REPO_NAME + ".jar"); } /** - * This method intializes and starts the metrics collection. + * This method loads the metric module and starts the metrics collection. */ public void start() { - Metrics metrics = new Metrics(plugin, 4574); - - if (SlimefunPlugin.getUpdater().getBranch().isOfficial()) { - // We really do not need this data if it is an unofficially modified build... - metrics.addCustomChart(new AutoUpdaterChart()); + boolean newlyDownloaded = false; + if (!metricFile.exists()) { + info(REPO_NAME + " does not exist, downloading..."); + download(getLatestVersion()); + newlyDownloaded = true; } - metrics.addCustomChart(new ResourcePackChart()); - metrics.addCustomChart(new SlimefunVersionChart()); - metrics.addCustomChart(new ServerLanguageChart()); - metrics.addCustomChart(new PlayerLanguageChart()); - metrics.addCustomChart(new ResearchesEnabledChart()); - metrics.addCustomChart(new GuideLayoutChart()); - metrics.addCustomChart(new AddonsChart()); - metrics.addCustomChart(new CommandChart()); - metrics.addCustomChart(new ServerSizeChart()); - metrics.addCustomChart(new CompatibilityModeChart()); + try { + // Load the jar file into a child class loader using the SF PluginClassLoader + // as a parent. + moduleClassLoader = URLClassLoader.newInstance(new URL[] { metricFile.toURI().toURL() }, + plugin.getClass().getClassLoader()); + Class cl = moduleClassLoader.loadClass("dev.walshy.sfmetrics.MetricsModule"); + + metricVersion = cl.getPackage().getImplementationVersion(); + + // If it has not been newly downloaded, auto-updates are on AND there's a new version + // then cleanup, download and start + if (!newlyDownloaded + && plugin.getConfig().getBoolean("metrics.auto-update") + && checkForUpdate(metricVersion) + ) { + info("Cleaning up and re-loading Metrics."); + cleanUp(); + start(); + return; + } + + // Finally, we're good to start this. + Method start = cl.getDeclaredMethod("start"); + String s = cl.getPackage().getImplementationVersion(); + System.out.println("Invoking start"); + Slimefun.runSync(() -> { + try { + start.invoke(null); + info("Metrics v" + s + " started."); + } catch (Exception e) { + plugin.getLogger().log(Level.WARNING, "Failed to start metrics.", e); + } + }); + } catch (Exception e) { + plugin.getLogger().log(Level.WARNING, + "Failed to load the metrics module. Maybe the jar is corrupt?", e); + } } + public void cleanUp() { + try { + if (this.moduleClassLoader != null) + this.moduleClassLoader.close(); + } catch (IOException e) { + plugin.getLogger().log(Level.WARNING, + "Could not clean up module class loader. Some memory may have been leaked."); + } + } + + public boolean checkForUpdate(String currentVersion) { + if (currentVersion.equals("UNOFFICIAL")) return false; + + int latest = getLatestVersion(); + if (latest > Integer.parseInt(currentVersion)) { + download(latest); + return true; + } + return false; + } + + private int getLatestVersion() { + try { + HttpResponse response = Unirest.get(GH_API + "/releases/latest") + .asJson(); + if (response.getStatus() < 200 || response.getStatus() >= 300) return -1; + + JsonNode node = response.getBody(); + + if (node == null) return -1; + + return node.getObject().getInt("tag_name"); + } catch (UnirestException e) { + plugin.getLogger().log(Level.SEVERE, "Failed to fetch latest builds for SFMetrics"); + return -1; + } + } + + private void download(int version) { + try { + if (metricFile.exists()) + metricFile.delete(); + + info("# Starting download of MetricsModule build: #" + version); + AtomicInteger lastPercentPosted = new AtomicInteger(); + HttpResponse response = Unirest.get(GH_REPO_RELEASES + "/" + version + + "/" + REPO_NAME + ".jar") + .downloadMonitor((b, fileName, bytesWritten, totalBytes) -> { + int percent = (int) (20 * (Math.round((((double) bytesWritten / totalBytes) * 100) / 20))); + + if (percent != 0 && percent != lastPercentPosted.get()) { + info("# Downloading... " + percent + "% " + + "(" + bytesWritten + "/" + totalBytes + " bytes)"); + lastPercentPosted.set(percent); + } + }) + .asFile(metricFile.getPath()); + if (response.getStatus() >= 200 && response.getStatus() < 300) { + info("Successfully downloaded " + REPO_NAME + " build: " + version); + metricVersion = String.valueOf(version); + } else + // If it failed we don't want this to be like a file containing "404 not found" + metricFile.delete(); + } catch (UnirestException e) { + plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the" + + " builds page. Perhaps GitHub is down."); + } + } + + private void info(String str) { + plugin.getLogger().info(str); + } + + @Nullable + public String getVersion() { + return metricVersion; + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/PlayerLanguageChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/PlayerLanguageChart.java deleted file mode 100644 index 347bf0640..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/PlayerLanguageChart.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import java.util.HashMap; -import java.util.Map; - -import org.bstats.bukkit.Metrics.AdvancedPie; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import io.github.thebusybiscuit.slimefun4.core.services.localization.Language; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class PlayerLanguageChart extends AdvancedPie { - - PlayerLanguageChart() { - super("player_languages", () -> { - Map languages = new HashMap<>(); - - for (Player p : Bukkit.getOnlinePlayers()) { - Language language = SlimefunPlugin.getLocalization().getLanguage(p); - boolean supported = SlimefunPlugin.getLocalization().isLanguageLoaded(language.getId()); - - String lang = supported ? language.getId() : "Unsupported Language"; - languages.merge(lang, 1, Integer::sum); - } - - return languages; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResearchesEnabledChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResearchesEnabledChart.java deleted file mode 100644 index 87a66bf2f..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResearchesEnabledChart.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class ResearchesEnabledChart extends SimplePie { - - ResearchesEnabledChart() { - super("servers_with_researches_enabled", () -> { - boolean enabled = SlimefunPlugin.getRegistry().isFreeCreativeResearchingEnabled(); - return enabled ? "enabled" : "disabled"; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResourcePackChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResourcePackChart.java deleted file mode 100644 index 0622c6e03..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ResourcePackChart.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class ResourcePackChart extends SimplePie { - - ResourcePackChart() { - super("resourcepack", () -> { - String version = SlimefunPlugin.getItemTextureService().getVersion(); - - if (version != null && version.startsWith("v")) { - return version + " (Official)"; - } - else if (SlimefunPlugin.getItemTextureService().isActive()) { - return "Custom / Modified"; - } - else { - return "None"; - } - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerLanguageChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerLanguageChart.java deleted file mode 100644 index e006eaf6d..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerLanguageChart.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; - -import io.github.thebusybiscuit.slimefun4.core.services.localization.Language; -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class ServerLanguageChart extends SimplePie { - - ServerLanguageChart() { - super("language", () -> { - Language language = SlimefunPlugin.getLocalization().getDefaultLanguage(); - boolean supported = SlimefunPlugin.getLocalization().isLanguageLoaded(language.getId()); - return supported ? language.getId() : "Unsupported Language"; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerSizeChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerSizeChart.java deleted file mode 100644 index 607859ba6..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/ServerSizeChart.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import org.bstats.bukkit.Metrics.SimplePie; -import org.bukkit.Bukkit; - -class ServerSizeChart extends SimplePie { - - ServerSizeChart() { - super("server_size", () -> { - int players = Bukkit.getOnlinePlayers().size(); - - if (players < 10) { - return "0-10"; - } - - if (players < 25) { - return "10-25"; - } - - if (players < 50) { - return "25-50"; - } - - if (players < 100) { - return "50-100"; - } - - if (players < 200) { - return "100-200"; - } - - if (players < 300) { - return "200-300"; - } - - return "300+"; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/SlimefunVersionChart.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/SlimefunVersionChart.java deleted file mode 100644 index 6140b60b0..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/SlimefunVersionChart.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; - -import java.util.HashMap; -import java.util.Map; - -import org.bstats.bukkit.Metrics.DrilldownPie; - -import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; - -class SlimefunVersionChart extends DrilldownPie { - - SlimefunVersionChart() { - super("slimefun_version", () -> { - Map> outerMap = new HashMap<>(); - Map innerMap = new HashMap<>(); - - innerMap.put(SlimefunPlugin.getVersion(), 1); - outerMap.put(SlimefunPlugin.getUpdater().getBranch().getName(), innerMap); - - return outerMap; - }); - } - -} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java index 2fd70f896..60ae3bf2f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java @@ -193,7 +193,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { networkManager = new NetworkManager(networkSize); // Setting up bStats - metricsService.start(); + new Thread(metricsService::start).start(); // Starting the Auto-Updater if (config.getBoolean("options.auto-update")) { @@ -364,6 +364,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { // Create a new backup zip backupService.run(); + metricsService.cleanUp(); + // Prevent Memory Leaks // These static Maps should be removed at some point... AContainer.processing = null; @@ -561,6 +563,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon { return instance.updaterService; } + /** + * This method returns the {@link MetricsService} of Slimefun. + * It is used to handle sending metric information to bStats. + * + * @return The {@link MetricsService} for Slimefun + */ + public static MetricsService getMetricsService() { + return instance.metricsService; + } + /** * This method returns the {@link GitHubService} of Slimefun. * It is used to retrieve data from GitHub repositories. diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a49e2e941..eca44c177 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -40,6 +40,9 @@ items: backpacks: true soulbound: true +metrics: + auto-update: true + research-ranks: - Chicken - Cow From fb40bffdcef155fda8c92dfddd261077af7a3492 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:17:24 +0100 Subject: [PATCH 03/16] Small change --- .../slimefun4/core/services/metrics/MetricsService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java index c1f1d6c9d..da8e50447 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java @@ -128,7 +128,7 @@ public class MetricsService { try { HttpResponse response = Unirest.get(GH_API + "/releases/latest") .asJson(); - if (response.getStatus() < 200 || response.getStatus() >= 300) return -1; + if (!response.isSuccess()) return -1; JsonNode node = response.getBody(); @@ -160,7 +160,7 @@ public class MetricsService { } }) .asFile(metricFile.getPath()); - if (response.getStatus() >= 200 && response.getStatus() < 300) { + if (response.isSuccess()) { info("Successfully downloaded " + REPO_NAME + " build: " + version); metricVersion = String.valueOf(version); } else From 50f034b3e36c459f8a992091868e35c2c2cb76ae Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:31:32 +0100 Subject: [PATCH 04/16] Documentation --- .../core/services/metrics/MetricsService.java | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java index da8e50447..a18d3fed6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java @@ -103,6 +103,10 @@ public class MetricsService { } } + /** + * This will close the child classloader and mark all the resources held under this no longer + * in use, they will be cleaned up the next GC run. + */ public void cleanUp() { try { if (this.moduleClassLoader != null) @@ -113,8 +117,15 @@ public class MetricsService { } } + /** + * Checks for a new update and compares it against the current version. + * If there is a new version available then this returns true. + * + * @param currentVersion The current version which is being used. + * @return True if there is an update available. + */ public boolean checkForUpdate(String currentVersion) { - if (currentVersion.equals("UNOFFICIAL")) return false; + if (currentVersion == null || currentVersion.equals("UNOFFICIAL")) return false; int latest = getLatestVersion(); if (latest > Integer.parseInt(currentVersion)) { @@ -124,6 +135,14 @@ public class MetricsService { return false; } + /** + * Gets the latest version available as an int. + * This is an internal method used by {@link #checkForUpdate(String)}. + * If it cannot get the version for whatever reason this will return 0, effectively always + * being behind. + * + * @return The latest version as an integer or -1 if it failed to fetch. + */ private int getLatestVersion() { try { HttpResponse response = Unirest.get(GH_API + "/releases/latest") @@ -141,6 +160,11 @@ public class MetricsService { } } + /** + * Downloads the version specified to Slimefun's data folder. + * + * @param version The version to download. + */ private void download(int version) { try { if (metricFile.exists()) @@ -176,8 +200,23 @@ public class MetricsService { plugin.getLogger().info(str); } + /** + * Returns the currently downloaded metric version. This CAN change! It may be null or an + * older version before it has downloaded a newer one. + * + * @return The current version or null if not loaded. + */ @Nullable public String getVersion() { return metricVersion; } + + /** + * Returns if the current server has metric auto-updates enabled. + * + * @return True if the current server has metric auto-updates enabled. + */ + public boolean hasAutoUpdates() { + return SlimefunPlugin.instance().getConfig().getBoolean("metrics.auto-update"); + } } From 8da64ab3083902766e14a61967a41b6620b4b079 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:35:31 +0100 Subject: [PATCH 05/16] Moved the metric class --- pom.xml | 4 ---- .../slimefun4/core/services/{metrics => }/MetricsService.java | 2 +- .../slimefun4/core/services/metrics/package-info.java | 4 ---- .../slimefun4/implementation/SlimefunPlugin.java | 2 +- 4 files changed, 2 insertions(+), 10 deletions(-) rename src/main/java/io/github/thebusybiscuit/slimefun4/core/services/{metrics => }/MetricsService.java (99%) delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/package-info.java diff --git a/pom.xml b/pom.xml index e51e138b6..dda17a51c 100644 --- a/pom.xml +++ b/pom.xml @@ -322,10 +322,6 @@ com.google.code.gson gson - - org.apache.httpcomponents - httpasyncclient - diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java similarity index 99% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index a18d3fed6..e7363bf6e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -1,4 +1,4 @@ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; +package io.github.thebusybiscuit.slimefun4.core.services; import javax.annotation.Nullable; import java.io.File; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/package-info.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/package-info.java deleted file mode 100644 index 3528603ca..000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/metrics/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * This package contains everything related to bStats Metrics - */ -package io.github.thebusybiscuit.slimefun4.core.services.metrics; \ No newline at end of file diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java index 60ae3bf2f..963d666c2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/SlimefunPlugin.java @@ -41,7 +41,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService; import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService; import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService; import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService; -import io.github.thebusybiscuit.slimefun4.core.services.metrics.MetricsService; +import io.github.thebusybiscuit.slimefun4.core.services.MetricsService; import io.github.thebusybiscuit.slimefun4.core.services.plugins.ThirdPartyPluginService; import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler; import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar; From 4d61a7db51ec16dafd1ea489b0ca72037d396f74 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:47:22 +0100 Subject: [PATCH 06/16] Reshade stupid bStats --- pom.xml | 10 ++++++++++ .../core/services/github/GitHubIssuesTracker.java | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dda17a51c..1ab90fec8 100644 --- a/pom.xml +++ b/pom.xml @@ -160,6 +160,10 @@ + + org.bstats + me.mrCookieSlime.Slimefun.bstats + io.github.thebusybiscuit.cscorelib2 @@ -313,6 +317,12 @@ 0.24 compile + + org.bstats + bstats-bukkit + 1.7 + compile + com.konghq unirest-java diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java index eb187dd37..e052fb978 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java @@ -38,7 +38,7 @@ class GitHubIssuesTracker extends GitHubConnector { // Don't even question why this is an Iterable for (Object elem : array) { - JSONObject obj = ((JsonNode) elem).getObject(); + JSONObject obj = (JSONObject) elem; if (obj.has("pull_request")) { pullRequests++; From 445853bf519bc2691d0bd233986b0f805b43065f Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:49:59 +0100 Subject: [PATCH 07/16] No one saw that --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 1ab90fec8..d5841a972 100644 --- a/pom.xml +++ b/pom.xml @@ -160,11 +160,11 @@ - - org.bstats - me.mrCookieSlime.Slimefun.bstats - + + org.bstats + me.mrCookieSlime.Slimefun.bstats + io.github.thebusybiscuit.cscorelib2 me.mrCookieSlime.Slimefun.cscorelib2 From d252e5a2b507b2898b21cc16f010fcff61f606e8 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 15:51:32 +0100 Subject: [PATCH 08/16] final final final small thing --- .../thebusybiscuit/slimefun4/core/services/MetricsService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index e7363bf6e..a0e1ec296 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -88,7 +88,8 @@ public class MetricsService { // Finally, we're good to start this. Method start = cl.getDeclaredMethod("start"); String s = cl.getPackage().getImplementationVersion(); - System.out.println("Invoking start"); + + // This is required to be sync due to bStats. Slimefun.runSync(() -> { try { start.invoke(null); From d31a293486b99779ccfea8f02e2abf382848d7a4 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Mon, 20 Jul 2020 16:04:49 +0100 Subject: [PATCH 09/16] Requested changes --- .../core/commands/subcommands/VersionsCommand.java | 11 ++++++----- .../slimefun4/core/services/MetricsService.java | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java index 1b533925b..476e5e4d6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java @@ -35,11 +35,12 @@ class VersionsCommand extends SubCommand { sender.sendMessage(ChatColors.color("&a" + Bukkit.getName() + " &2" + ReflectionUtils.getVersion())); sender.sendMessage(""); sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion())); - sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()) - + (SlimefunPlugin.getMetricsService().getVersion() != null - ? " (Metrics build: #" + SlimefunPlugin.getMetricsService().getVersion() + ')' - : "") - ); + + String version = "&aSlimefun &2v" + SlimefunPlugin.getVersion(); + if (SlimefunPlugin.getMetricsService().getVersion() != null) + version += "&7 (Metrics build: &2#" + SlimefunPlugin.getMetricsService().getVersion() + ')'; + + sender.sendMessage(ChatColors.color(version)); if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) { sender.sendMessage(ChatColor.YELLOW + "Backwards compatiblity enabled!"); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index a0e1ec296..b9b8b69c8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -25,6 +25,7 @@ import org.bukkit.plugin.Plugin; * Note: To start the metrics you will need to be calling {@link #start()} * * @author TheBusyBiscuit + * @author WalshyDev */ public class MetricsService { From 58dbbd894476d046071c5cc1a9f9911a14cdf036 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 21 Jul 2020 08:47:36 +0100 Subject: [PATCH 10/16] Better handling of downloaded files, typo fix and small changes --- .../commands/subcommands/VersionsCommand.java | 8 ++--- .../core/services/MetricsService.java | 34 ++++++++++++------- .../core/services/github/GitHubConnector.java | 26 ++++++++++++++ .../services/github/GitHubIssuesTracker.java | 5 ++- 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java index 476e5e4d6..547d5a821 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/commands/subcommands/VersionsCommand.java @@ -35,15 +35,13 @@ class VersionsCommand extends SubCommand { sender.sendMessage(ChatColors.color("&a" + Bukkit.getName() + " &2" + ReflectionUtils.getVersion())); sender.sendMessage(""); sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion())); + sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion())); - String version = "&aSlimefun &2v" + SlimefunPlugin.getVersion(); if (SlimefunPlugin.getMetricsService().getVersion() != null) - version += "&7 (Metrics build: &2#" + SlimefunPlugin.getMetricsService().getVersion() + ')'; - - sender.sendMessage(ChatColors.color(version)); + sender.sendMessage(ChatColors.color("&aMetrics: &2#" + SlimefunPlugin.getMetricsService().getVersion() + ')')); if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) { - sender.sendMessage(ChatColor.YELLOW + "Backwards compatiblity enabled!"); + sender.sendMessage(ChatColor.YELLOW + "Backwards compatibility enabled!"); } sender.sendMessage(""); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index b9b8b69c8..ee951bfde 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -6,6 +6,8 @@ import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; @@ -61,7 +63,10 @@ public class MetricsService { boolean newlyDownloaded = false; if (!metricFile.exists()) { info(REPO_NAME + " does not exist, downloading..."); - download(getLatestVersion()); + if (!download(getLatestVersion())) { + plugin.getLogger().warning("Failed to start metrics as the file could not be downloaded."); + return; + } newlyDownloaded = true; } @@ -77,7 +82,7 @@ public class MetricsService { // If it has not been newly downloaded, auto-updates are on AND there's a new version // then cleanup, download and start if (!newlyDownloaded - && plugin.getConfig().getBoolean("metrics.auto-update") + && hasAutoUpdates() && checkForUpdate(metricVersion) ) { info("Cleaning up and re-loading Metrics."); @@ -131,8 +136,7 @@ public class MetricsService { int latest = getLatestVersion(); if (latest > Integer.parseInt(currentVersion)) { - download(latest); - return true; + return download(latest); } return false; } @@ -167,11 +171,10 @@ public class MetricsService { * * @param version The version to download. */ - private void download(int version) { - try { - if (metricFile.exists()) - metricFile.delete(); + private boolean download(int version) { + File f = new File(plugin.getDataFolder(), "Metrics-" + version + ".jar"); + try { info("# Starting download of MetricsModule build: #" + version); AtomicInteger lastPercentPosted = new AtomicInteger(); HttpResponse response = Unirest.get(GH_REPO_RELEASES + "/" + version @@ -185,17 +188,24 @@ public class MetricsService { lastPercentPosted.set(percent); } }) - .asFile(metricFile.getPath()); + .asFile(f.getPath()); if (response.isSuccess()) { info("Successfully downloaded " + REPO_NAME + " build: " + version); + + // Replace the metric file with the new one + Files.move(f.toPath(), metricFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + metricVersion = String.valueOf(version); - } else - // If it failed we don't want this to be like a file containing "404 not found" - metricFile.delete(); + return true; + } } catch (UnirestException e) { plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the" + " builds page. Perhaps GitHub is down."); + } catch (IOException e) { + plugin.getLogger().log(Level.WARNING, "Failed to replace the old metric file with the " + + "new one. Please do this manually! Error: {0}", e.getMessage()); } + return false; } private void info(String str) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java index 90bfbc767..4c99df80d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java @@ -1,15 +1,20 @@ package io.github.thebusybiscuit.slimefun4.core.services.github; +import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.logging.Level; import kong.unirest.HttpResponse; import kong.unirest.JsonNode; import kong.unirest.Unirest; import kong.unirest.UnirestException; +import kong.unirest.json.JSONException; import me.mrCookieSlime.Slimefun.api.Slimefun; abstract class GitHubConnector { @@ -56,10 +61,31 @@ abstract class GitHubConnector { if (github.isLoggingEnabled()) { Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time."); } + + // It has the cached file, let's just read that then + if (file.exists()) { + JsonNode cache = readCacheFile(); + if (cache != null) { + onSuccess(cache); + return; + } + } + + // If the request failed and it failed to read the cache then call onFailure. onFailure(); } } + private JsonNode readCacheFile() { + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + return new JsonNode(br.readLine()); + } catch (IOException | JSONException e) { + Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0}", + file.getName()); + return null; + } + } + private void writeCacheFile(JsonNode node) { try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(node.toString().getBytes(StandardCharsets.UTF_8)); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java index e052fb978..066ba8956 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubIssuesTracker.java @@ -36,9 +36,8 @@ class GitHubIssuesTracker extends GitHubConnector { int issues = 0; int pullRequests = 0; - // Don't even question why this is an Iterable - for (Object elem : array) { - JSONObject obj = (JSONObject) elem; + for (int i = 0; i < array.length(); i++) { + JSONObject obj = array.getJSONObject(i); if (obj.has("pull_request")) { pullRequests++; From f632dee5600d42615f37f682915654a2ca3ca49b Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 21 Jul 2020 13:59:48 +0100 Subject: [PATCH 11/16] Modify changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5ac5d68d..b6927dd28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ ## Release Candidate 15 (TBD) +#### Additions +* Added a [Metric module](https://github.com/Slimefun/MetricsModule) which allows us to deploy changes to metrics (bStats) without another Slimefun build. + #### Changes * Refactored and reworked the Generator API * Small performance improvements to Energy networks From 2646eba615f131bccb2ff9496f5905376104b412 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 21 Jul 2020 14:51:04 +0100 Subject: [PATCH 12/16] Small change --- .../thebusybiscuit/slimefun4/core/services/MetricsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index ee951bfde..026700ff7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -99,7 +99,7 @@ public class MetricsService { Slimefun.runSync(() -> { try { start.invoke(null); - info("Metrics v" + s + " started."); + info("Metrics build " + s + " started."); } catch (Exception e) { plugin.getLogger().log(Level.WARNING, "Failed to start metrics.", e); } From 01b653ff39c00c1e507671e8f2270f2615c1f9af Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Wed, 22 Jul 2020 20:07:55 +0100 Subject: [PATCH 13/16] Fix the critical game-breaking bug --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7ec5eba36..1e7d52776 100644 --- a/pom.xml +++ b/pom.xml @@ -331,8 +331,7 @@ com.konghq unirest-java 3.8.06 - + com.google.code.gson gson From d547d611513da1e61c45d4596847571f926763b0 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Wed, 22 Jul 2020 20:45:55 +0100 Subject: [PATCH 14/16] Requested changes --- .../core/services/MetricsService.java | 27 ++++++++++--------- .../core/services/github/GitHubConnector.java | 3 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index 026700ff7..0db9afe69 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.github.thebusybiscuit.slimefun4.utils.PatternUtils; import kong.unirest.HttpResponse; import kong.unirest.JsonNode; import kong.unirest.Unirest; @@ -41,6 +42,7 @@ public class MetricsService { private URLClassLoader moduleClassLoader; private String metricVersion = null; + private boolean newlyDownloaded = false; static { Unirest.config() @@ -60,9 +62,8 @@ public class MetricsService { * This method loads the metric module and starts the metrics collection. */ public void start() { - boolean newlyDownloaded = false; if (!metricFile.exists()) { - info(REPO_NAME + " does not exist, downloading..."); + plugin.getLogger().info(REPO_NAME + " does not exist, downloading..."); if (!download(getLatestVersion())) { plugin.getLogger().warning("Failed to start metrics as the file could not be downloaded."); return; @@ -85,7 +86,7 @@ public class MetricsService { && hasAutoUpdates() && checkForUpdate(metricVersion) ) { - info("Cleaning up and re-loading Metrics."); + plugin.getLogger().info("Cleaning up and re-loading Metrics."); cleanUp(); start(); return; @@ -99,7 +100,7 @@ public class MetricsService { Slimefun.runSync(() -> { try { start.invoke(null); - info("Metrics build " + s + " started."); + plugin.getLogger().info("Metrics build " + s + " started."); } catch (Exception e) { plugin.getLogger().log(Level.WARNING, "Failed to start metrics.", e); } @@ -132,7 +133,12 @@ public class MetricsService { * @return True if there is an update available. */ public boolean checkForUpdate(String currentVersion) { - if (currentVersion == null || currentVersion.equals("UNOFFICIAL")) return false; + if (currentVersion == null + || currentVersion.equals("UNOFFICIAL") + || !PatternUtils.NUMERIC.matcher(currentVersion).matches() + ) { + return false; + } int latest = getLatestVersion(); if (latest > Integer.parseInt(currentVersion)) { @@ -175,7 +181,7 @@ public class MetricsService { File f = new File(plugin.getDataFolder(), "Metrics-" + version + ".jar"); try { - info("# Starting download of MetricsModule build: #" + version); + plugin.getLogger().info("# Starting download of MetricsModule build: #" + version); AtomicInteger lastPercentPosted = new AtomicInteger(); HttpResponse response = Unirest.get(GH_REPO_RELEASES + "/" + version + "/" + REPO_NAME + ".jar") @@ -183,19 +189,20 @@ public class MetricsService { int percent = (int) (20 * (Math.round((((double) bytesWritten / totalBytes) * 100) / 20))); if (percent != 0 && percent != lastPercentPosted.get()) { - info("# Downloading... " + percent + "% " + + plugin.getLogger().info("# Downloading... " + percent + "% " + "(" + bytesWritten + "/" + totalBytes + " bytes)"); lastPercentPosted.set(percent); } }) .asFile(f.getPath()); if (response.isSuccess()) { - info("Successfully downloaded " + REPO_NAME + " build: " + version); + plugin.getLogger().info("Successfully downloaded " + REPO_NAME + " build: " + version); // Replace the metric file with the new one Files.move(f.toPath(), metricFile.toPath(), StandardCopyOption.REPLACE_EXISTING); metricVersion = String.valueOf(version); + newlyDownloaded = true; return true; } } catch (UnirestException e) { @@ -208,10 +215,6 @@ public class MetricsService { return false; } - private void info(String str) { - plugin.getLogger().info(str); - } - /** * Returns the currently downloaded metric version. This CAN change! It may be null or an * older version before it has downloaded a newer one. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java index 4c99df80d..3b8976fc5 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubConnector.java @@ -6,6 +6,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.logging.Level; @@ -77,7 +78,7 @@ abstract class GitHubConnector { } private JsonNode readCacheFile() { - try (BufferedReader br = new BufferedReader(new FileReader(file))) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { return new JsonNode(br.readLine()); } catch (IOException | JSONException e) { Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0}", From 6f92bd6c28f44be33accf49dfb9d9e890b971315 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Thu, 23 Jul 2020 09:51:35 +0100 Subject: [PATCH 15/16] Requested changes --- .../slimefun4/core/services/MetricsService.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index 0db9afe69..71333e145 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -55,7 +55,12 @@ public class MetricsService { public MetricsService(SlimefunPlugin plugin) { this.plugin = plugin; - this.metricFile = new File(plugin.getDataFolder(), REPO_NAME + ".jar"); + + File parentFile = new File(plugin.getDataFolder(), "cache" + File.separatorChar + "modules"); + if (!parentFile.exists()) + parentFile.mkdirs(); + + this.metricFile = new File(parentFile , REPO_NAME + ".jar"); } /** @@ -68,7 +73,6 @@ public class MetricsService { plugin.getLogger().warning("Failed to start metrics as the file could not be downloaded."); return; } - newlyDownloaded = true; } try { @@ -94,13 +98,13 @@ public class MetricsService { // Finally, we're good to start this. Method start = cl.getDeclaredMethod("start"); - String s = cl.getPackage().getImplementationVersion(); + String version = cl.getPackage().getImplementationVersion(); // This is required to be sync due to bStats. Slimefun.runSync(() -> { try { start.invoke(null); - plugin.getLogger().info("Metrics build " + s + " started."); + plugin.getLogger().info("Metrics build #" + version + " started."); } catch (Exception e) { plugin.getLogger().log(Level.WARNING, "Failed to start metrics.", e); } @@ -133,10 +137,7 @@ public class MetricsService { * @return True if there is an update available. */ public boolean checkForUpdate(String currentVersion) { - if (currentVersion == null - || currentVersion.equals("UNOFFICIAL") - || !PatternUtils.NUMERIC.matcher(currentVersion).matches() - ) { + if (currentVersion == null || !PatternUtils.NUMERIC.matcher(currentVersion).matches()) { return false; } From b13776d729a182ea50aec5e7058455447ae3bdbb Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Thu, 23 Jul 2020 10:37:23 +0100 Subject: [PATCH 16/16] Final changes --- .../slimefun4/core/services/MetricsService.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java index 71333e145..2b9137dc6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/MetricsService.java @@ -38,6 +38,7 @@ public class MetricsService { + "/releases/download"; private final SlimefunPlugin plugin; + private final File parentFolder; private final File metricFile; private URLClassLoader moduleClassLoader; @@ -56,11 +57,11 @@ public class MetricsService { public MetricsService(SlimefunPlugin plugin) { this.plugin = plugin; - File parentFile = new File(plugin.getDataFolder(), "cache" + File.separatorChar + "modules"); - if (!parentFile.exists()) - parentFile.mkdirs(); + this.parentFolder = new File(plugin.getDataFolder(), "cache" + File.separatorChar + "modules"); + if (!parentFolder.exists()) + parentFolder.mkdirs(); - this.metricFile = new File(parentFile , REPO_NAME + ".jar"); + this.metricFile = new File(parentFolder, REPO_NAME + ".jar"); } /** @@ -179,7 +180,7 @@ public class MetricsService { * @param version The version to download. */ private boolean download(int version) { - File f = new File(plugin.getDataFolder(), "Metrics-" + version + ".jar"); + File f = new File(parentFolder, "Metrics-" + version + ".jar"); try { plugin.getLogger().info("# Starting download of MetricsModule build: #" + version);