From 5a8d39a3a053ba3e714c2af8c9e133e6345ffdb1 Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Sun, 16 Dec 2018 14:47:42 +1300 Subject: [PATCH] Ability to check jenkin builds, rewritten version checking, show build number, config option for update check type, show console update notifications, minor change in string for update check --- pom.xml | 3 +- .../disguise/DisguiseConfig.java | 25 ++- .../disguise/DisguiseListener.java | 132 ++++++++++----- .../libraryaddict/disguise/LibsDisguises.java | 56 +++++-- .../commands/LibsDisguisesCommand.java | 15 +- .../disguise/utilities/LibsMsg.java | 6 +- .../disguise/utilities/LibsPremium.java | 9 +- .../disguise/utilities/Metrics.java | 26 ++- .../disguise/utilities/ReflectionManager.java | 19 +++ .../disguise/utilities/UpdateChecker.java | 157 ++++++++++++++---- src/main/resources/config.yml | 6 + src/main/resources/plugin.yml | 6 +- 12 files changed, 352 insertions(+), 108 deletions(-) diff --git a/pom.xml b/pom.xml index eadbb533..27076526 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ LibsDisguises LibsDisguises - 9.7.0 + 9.7.0-SNAPSHOT clean install @@ -35,6 +35,7 @@ + unknown 1.8 1.8 UTF-8 diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java index 1bb8799d..47e93a07 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java @@ -22,6 +22,12 @@ public class DisguiseConfig { CREATE_SCOREBOARD; } + public enum UpdatesBranch { + SAME_BUILDS, + SNAPSHOTS, + RELEASES + } + private static boolean animationEnabled; private static boolean bedEnabled; private static boolean blowDisguisesWhenAttacking; @@ -69,6 +75,15 @@ public class DisguiseConfig { private static boolean explicitDisguisePermissions; private static boolean disableCommands; private static int uuidGeneratedVersion; + private static UpdatesBranch updatesBranch = UpdatesBranch.SAME_BUILDS; + + public static UpdatesBranch getUpdatesBranch() { + return updatesBranch; + } + + public static void setUpdatesBranch(UpdatesBranch newBranch) { + updatesBranch = newBranch; + } public static int getUUIDGeneratedVersion() { return uuidGeneratedVersion; @@ -260,6 +275,14 @@ public class DisguiseConfig { DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!"); } + try { + setUpdatesBranch(UpdatesBranch.valueOf(config.getString("UpdatesBranch").toUpperCase())); + } + catch (Exception ex) { + DisguiseUtilities.getLogger().warning("Cannot parse '" + config.getString("UpdatesBranch") + + "' to a valid option for UpdatesBranch"); + } + try { String option = config.getString("SelfDisguisesScoreboard", DisguisePushing.MODIFY_SCOREBOARD.name()) .toUpperCase(); @@ -270,7 +293,7 @@ public class DisguiseConfig { disablePushing = DisguisePushing.valueOf(option); } catch (Exception ex) { - DisguiseUtilities.getLogger().info("Cannot parse '" + config.getString("SelfDisguisesScoreboard") + + DisguiseUtilities.getLogger().warning("Cannot parse '" + config.getString("SelfDisguisesScoreboard") + "' to a valid option for SelfDisguisesTeam"); } diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseListener.java b/src/main/java/me/libraryaddict/disguise/DisguiseListener.java index be4a8c28..e93090fd 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseListener.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseListener.java @@ -23,6 +23,7 @@ import me.libraryaddict.disguise.utilities.parser.DisguisePermissions; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -47,60 +48,23 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.concurrent.TimeUnit; public class DisguiseListener implements Listener { - private String currentVersion; private HashMap disguiseClone = new HashMap<>(); private HashMap disguiseEntity = new HashMap<>(); private HashMap disguiseModify = new HashMap<>(); private HashMap disguiseRunnable = new HashMap<>(); private String latestVersion; + private LibsMsg updateMessage; private LibsDisguises plugin; private BukkitTask updaterTask; public DisguiseListener(LibsDisguises libsDisguises) { plugin = libsDisguises; - if (plugin.getConfig().getBoolean("NotifyUpdate")) { - currentVersion = plugin.getDescription().getVersion(); - - updaterTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { - @Override - public void run() { - try { - UpdateChecker updateChecker = new UpdateChecker(); - updateChecker.checkUpdate("v" + currentVersion); - - latestVersion = updateChecker.getLatestVersion(); - - if (latestVersion == null) { - return; - } - - latestVersion = "v" + latestVersion; - - Bukkit.getScheduler().runTask(plugin, new Runnable() { - @Override - public void run() { - for (Player p : Bukkit.getOnlinePlayers()) { - if (!p.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) { - continue; - } - - p.sendMessage(LibsMsg.UPDATE_READY.get(currentVersion, latestVersion)); - } - } - }); - } - catch (Exception ex) { - DisguiseUtilities.getLogger() - .warning(String.format("Failed to check for update: %s", ex.getMessage())); - } - } - }, 0, (20 * 60 * 60 * 6)); // Check every 6 hours - // 20 ticks * 60 seconds * 60 minutes * 6 hours - } + runUpdateScheduler(); if (!DisguiseConfig.isSaveEntityDisguises()) return; @@ -122,6 +86,90 @@ public class DisguiseListener implements Listener { } } + private boolean isCheckReleases() { + if (DisguiseConfig.getUpdatesBranch() == DisguiseConfig.UpdatesBranch.RELEASES) { + return true; + } + + if (DisguiseConfig.getUpdatesBranch() == DisguiseConfig.UpdatesBranch.SAME_BUILDS && plugin.isReleaseBuild()) { + return true; + } + + // If build number is null, or not a number. Then we can't check snapshots regardless + if (plugin.getBuildNo() == null || !plugin.getBuildNo().matches("[0-9]+")) { + return true; + } + + // Check snapshots + return false; + } + + private void runUpdateScheduler() { + if (!plugin.getConfig().getBoolean("NotifyUpdate")) { + return; + } + + updaterTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { + @Override + public void run() { + try { + UpdateChecker updateChecker = new UpdateChecker("32453"); + boolean checkReleases = isCheckReleases(); + + if (checkReleases) { + currentVersion = plugin.getDescription().getVersion(); + updateChecker.checkOfficialUpdate(currentVersion); + String version = updateChecker.getLatestVersion(); + + if (version == null) { + return; + } + + latestVersion = version; + updateMessage = LibsMsg.UPDATE_READY; + } else { + updateChecker.checkSnapshotUpdate(Integer.parseInt(plugin.getBuildNo())); + + if (updateChecker.getLatestSnapshot() <= 0) { + return; + } + + currentVersion = plugin.getBuildNo(); + latestVersion = "" + updateChecker.getLatestSnapshot(); + updateMessage = LibsMsg.UPDATE_READY_SNAPSHOT; + } + + Bukkit.getScheduler().runTask(plugin, new Runnable() { + @Override + public void run() { + notifyUpdate(Bukkit.getConsoleSender()); + + for (Player p : Bukkit.getOnlinePlayers()) { + notifyUpdate(p); + } + } + }); + } + catch (Exception ex) { + DisguiseUtilities.getLogger() + .warning(String.format("Failed to check for update: %s", ex.getMessage())); + } + } + }, 0, (20 * TimeUnit.HOURS.toSeconds(6))); // Check every 6 hours + } + + private void notifyUpdate(CommandSender player) { + if (!player.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) { + return; + } + + if (latestVersion == null) { + return; + } + + player.sendMessage(updateMessage.get(currentVersion, latestVersion)); + } + public void cleanup() { for (BukkitRunnable r : disguiseRunnable.values()) { r.cancel(); @@ -284,9 +332,7 @@ public class DisguiseListener implements Listener { public void onJoin(PlayerJoinEvent event) { Player p = event.getPlayer(); - if (latestVersion != null && p.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) { - p.sendMessage(LibsMsg.UPDATE_READY.get(currentVersion, latestVersion)); - } + notifyUpdate(p); if (DisguiseConfig.isBedPacketsEnabled()) { chunkMove(p, p.getLocation(), null); diff --git a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java index 1148bf24..88a12945 100644 --- a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java @@ -13,6 +13,7 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandExecutor; import org.bukkit.command.PluginCommand; import org.bukkit.command.TabCompleter; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.*; import org.bukkit.plugin.java.JavaPlugin; @@ -27,23 +28,32 @@ import java.util.HashSet; public class LibsDisguises extends JavaPlugin { private static LibsDisguises instance; private DisguiseListener listener; + private String buildNumber; @Override public void onEnable() { instance = this; - getLogger().info("Discovered nms version: " + ReflectionManager.getBukkitVersion()); - if (!new File(getDataFolder(), "disguises.yml").exists()) { saveResource("disguises.yml", false); } + YamlConfiguration pluginYml = ReflectionManager.getPluginYaml(getClassLoader()); + buildNumber = StringUtils.stripToNull(pluginYml.getString("build-number")); + + getLogger().info("Discovered nms version: " + ReflectionManager.getBukkitVersion()); + + boolean hashBuild = getBuildNo() != null && getBuildNo().matches("[0-9]+"); + getLogger().info("Jenkins Build: " + (hashBuild ? "#" : "") + getBuildNo()); + LibsPremium.check(getDescription().getVersion()); if (ReflectionManager.getMinecraftVersion().startsWith("1.13")) { if (!LibsPremium.isPremium()) { getLogger().severe("You must purchase the plugin to use 1.13!"); - getLogger().severe("This will be released in just a few days, or you can buy it now for 50% off with all premium-only features included!"); + getLogger() + .severe("This will be released in just a few days, or you can buy it now for 50% off with all" + + " premium-only features included!"); getLogger().severe("If you've already purchased the plugin, place the purchased jar inside the " + "Lib's Disguises plugin folder"); getPluginLoader().disablePlugin(this); @@ -92,8 +102,25 @@ public class LibsDisguises extends JavaPlugin { infectWithMetrics(); } + @Override + public void onDisable() { + DisguiseUtilities.saveDisguises(); + + for (Player player : Bukkit.getOnlinePlayers()) { + DisguiseUtilities.removeSelfDisguiseScoreboard(player); + } + } + private void infectWithMetrics() { - Metrics metrics = new Metrics(this); + String version = getDescription().getVersion(); + + // If a release build, attach build number + if (!isReleaseBuild()) { + // 9.7.0-SNAPSHOT-b30 + version += "-b" + getBuildNo(); + } + + Metrics metrics = new Metrics(this, version); final String premium = LibsPremium.isPremium() ? getDescription().getVersion().contains("SNAPSHOT") ? "Paid Builds" : "Paid Plugin" : "Free Builds"; @@ -209,7 +236,6 @@ public class LibsDisguises extends JavaPlugin { } }); - metrics.addCustomChart(new Metrics.SimplePie("commands") { @Override public String getValue() { @@ -239,6 +265,15 @@ public class LibsDisguises extends JavaPlugin { } }); + if (getBuildNo() != null) { + metrics.addCustomChart(new Metrics.SimplePie("build_number") { + @Override + public String getValue() { + return getBuildNo(); + } + }); + } + metrics.addCustomChart(new Metrics.SimplePie("targeted_disguises") { /** * Store value just to minimize amount of times it's called, and to persist even when not using anymore @@ -271,13 +306,12 @@ public class LibsDisguises extends JavaPlugin { }); } - @Override - public void onDisable() { - DisguiseUtilities.saveDisguises(); + public boolean isReleaseBuild() { + return !getDescription().getVersion().contains("-SNAPSHOT"); + } - for (Player player : Bukkit.getOnlinePlayers()) { - DisguiseUtilities.removeSelfDisguiseScoreboard(player); - } + public String getBuildNo() { + return buildNumber; } private void registerCommand(String commandName, CommandExecutor executioner) { diff --git a/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java b/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java index 8bb7e6c6..b551e5a5 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java @@ -1,9 +1,9 @@ package me.libraryaddict.disguise.commands; import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.utilities.LibsMsg; import me.libraryaddict.disguise.utilities.LibsPremium; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -52,9 +52,16 @@ public class LibsDisguisesCommand implements CommandExecutor, TabCompleter { @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { if (args.length == 0) { - sender.sendMessage(ChatColor.DARK_GREEN + "This server is running " + "Lib's Disguises v" + - Bukkit.getPluginManager().getPlugin("LibsDisguises").getDescription().getVersion() + - " by libraryaddict, formerly maintained " + "by Byteflux and NavidK0." + + LibsDisguises disguises = LibsDisguises.getInstance(); + + String version = disguises.getDescription().getVersion(); + + if (!disguises.isReleaseBuild()) { + version += "-b" + disguises.getBuildNo(); + } + + sender.sendMessage(ChatColor.DARK_GREEN + "This server is running " + "Lib's Disguises v" + version + + " by libraryaddict, formerly maintained by Byteflux and NavidK0." + (sender.hasPermission("libsdisguises.reload") ? "\nUse " + ChatColor.GREEN + "/libsdisguises " + "reload" + ChatColor.DARK_GREEN + " to reload the config. All disguises will be blown by doing this" + "." : "")); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/LibsMsg.java b/src/main/java/me/libraryaddict/disguise/utilities/LibsMsg.java index 9efcf5d3..49b4edea 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/LibsMsg.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/LibsMsg.java @@ -167,7 +167,11 @@ public enum LibsMsg { UNDISRADIUS(ChatColor.RED + "Successfully undisguised %s entities!"), UPDATE_READY(ChatColor.RED + "[LibsDisguises] " + ChatColor.DARK_RED + "There is a update ready to be downloaded! You are using " + ChatColor.RED + "v%s" + ChatColor.DARK_RED + - ", the new version is " + ChatColor.RED + "%s" + ChatColor.DARK_RED + "!"), + ", the new version is " + ChatColor.RED + "v%s" + ChatColor.DARK_RED + "!"), + UPDATE_READY_SNAPSHOT(ChatColor.RED + "[LibsDisguises] " + ChatColor.DARK_RED + + "There is a new build of Lib's Disguises! You are using " + ChatColor.RED + "#%s" + + ChatColor.DARK_RED + ", the latest build is " + ChatColor.RED + "#%s" + ChatColor.DARK_RED + "!" + + ChatColor.RED + "\nhttps://ci.md-5.net/job/LibsDisguises/lastSuccessfulBuild/"), VIEW_SELF_ON(ChatColor.GREEN + "Toggled viewing own disguise on!"), VIEW_SELF_OFF(ChatColor.GREEN + "Toggled viewing own disguise off!"); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/LibsPremium.java b/src/main/java/me/libraryaddict/disguise/utilities/LibsPremium.java index 59a1698f..2568ceee 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/LibsPremium.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/LibsPremium.java @@ -1,10 +1,8 @@ package me.libraryaddict.disguise.utilities; -import org.apache.commons.io.IOUtils; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; -import java.io.InputStream; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; @@ -42,12 +40,9 @@ public class LibsPremium { thisPluginIsPaidFor = (Boolean) m.invoke(null); String pluginVersion; - try (InputStream stream = cl.getResourceAsStream("plugin.yml")) { - YamlConfiguration config = new YamlConfiguration(); - config.loadFromString(IOUtils.toString(stream, "UTF-8")); + YamlConfiguration config = ReflectionManager.getPluginYaml(cl); - pluginVersion = config.getString("version"); - } + pluginVersion = config.getString("version"); if (isPremium()) { // Found a premium Lib's Disguises jar (v5.2.6), premium enabled! diff --git a/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java b/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java index 79ecb62b..0daa4883 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java @@ -31,8 +31,8 @@ public class Metrics { final String examplePackage = new String( new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); // We want to make sure nobody just copy & pastes the example and use the wrong package names - if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName() - .equals(examplePackage)) { + if (Metrics.class.getPackage().getName().equals(defaultPackage) || + Metrics.class.getPackage().getName().equals(examplePackage)) { throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); } } @@ -51,6 +51,8 @@ public class Metrics { // The plugin private final JavaPlugin plugin; + // The plugin version + private final String version; // A list with all custom charts private final List charts = new ArrayList<>(); @@ -60,11 +62,13 @@ public class Metrics { * * @param plugin The plugin which stats should be submitted. */ - public Metrics(JavaPlugin plugin) { + public Metrics(JavaPlugin plugin, String version) { if (plugin == null) { throw new IllegalArgumentException("Plugin cannot be null!"); } + this.plugin = plugin; + this.version = version; // Get the config file File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); @@ -83,8 +87,11 @@ public class Metrics { // Inform the server owners about bStats config.options() - .header("bStats collects some data for plugin authors like how many servers are using their plugins.\n" + "To honor their work, you should not disable it.\n" + "This has nearly no effect on the server performance!\n" + "Check out https://bStats.org/ to learn more :)") - .copyDefaults(true); + .header("bStats collects some data for plugin authors like how many servers are using their " + + "plugins.\n" + + "To honor their work, you should not disable it.\n" + + "This has nearly no effect on the server performance!\n" + + "Check out https://bStats.org/ to learn more :)").copyDefaults(true); try { config.save(configFile); } @@ -140,8 +147,10 @@ public class Metrics { timer.cancel(); return; } - // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler - // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) + // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit + // scheduler + // Don't be afraid! The connection to the bStats server is still async, only the stats collection is + // sync ;) Bukkit.getScheduler().runTask(plugin, new Runnable() { @Override public void run() { @@ -165,10 +174,9 @@ public class Metrics { JSONObject data = new JSONObject(); String pluginName = plugin.getDescription().getName(); - String pluginVersion = plugin.getDescription().getVersion(); data.put("pluginName", pluginName); // Append the name of the plugin - data.put("pluginVersion", pluginVersion); // Append the version of the plugin + data.put("pluginVersion", version); // Append the version of the plugin JSONArray customCharts = new JSONArray(); for (CustomChart customChart : charts) { // Add the data of the custom charts diff --git a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java index 7e01a0b2..1cae4fd4 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -8,12 +8,17 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObje import com.comphenix.protocol.wrappers.nbt.NbtWrapper; import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import org.apache.commons.io.IOUtils; import org.bukkit.*; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.*; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; +import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.*; import java.nio.ByteBuffer; import java.util.Optional; @@ -80,6 +85,20 @@ public class ReflectionManager { entityCountField.setAccessible(true); } + public static YamlConfiguration getPluginYaml(ClassLoader loader) { + try (InputStream stream = loader.getResourceAsStream("plugin.yml")) { + YamlConfiguration config = new YamlConfiguration(); + config.loadFromString(IOUtils.toString(stream, "UTF-8")); + + return config; + } + catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + } + + return null; + } + public static int getNewEntityId() { return getNewEntityId(true); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java b/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java index 212f8650..6f7399a5 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java @@ -1,29 +1,60 @@ package me.libraryaddict.disguise.utilities; -import java.io.BufferedReader; -import java.io.InputStreamReader; +import com.google.gson.Gson; +import org.apache.commons.io.IOUtils; + +import java.io.InputStream; +import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; -import java.util.regex.Pattern; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.TimeUnit; public class UpdateChecker { - + private final String resourceID; private String latestVersion; + private int latestSnapshot; - private boolean checkHigher(String currentVersion, String newVersion) { - String current = toReadable(currentVersion); - String newVers = toReadable(newVersion); - return current.compareTo(newVers) < 0; + public UpdateChecker(String resourceID) { + this.resourceID = resourceID; } - public void checkUpdate(String currentVersion) { - String version = getSpigotVersion(); + public void checkSnapshotUpdate(int buildNumber) { + Map lastBuild = fetchLastSnapshotBuild(); - if (version == null) + if (lastBuild == null || !lastBuild.containsKey("id") || !lastBuild.containsKey("timestamp")) { return; + } - if (!checkHigher(currentVersion, version)) + int newBuildNumber = Integer.parseInt((String) lastBuild.get("id")); + + // If new build number is same or older + if (newBuildNumber <= buildNumber) { return; + } + + Date newBuildDate = new Date(((Number) lastBuild.get("timestamp")).longValue()); + + // If the new snapshot is at least 3 days old + /*if (newBuildDate.getTime() >= System.currentTimeMillis() - TimeUnit.DAYS.toMillis(3)) { + return; + }*/ + + latestSnapshot = newBuildNumber; + } + + public void checkOfficialUpdate(String currentVersion) { + String version = fetchSpigotVersion(); + + if (version == null) { + return; + } + + if (!isNewerVersion(currentVersion, version)) { + return; + } latestVersion = version; } @@ -32,21 +63,41 @@ public class UpdateChecker { return latestVersion; } + public int getLatestSnapshot() { + return latestSnapshot; + } + /** * Asks spigot for the version */ - private String getSpigotVersion() { + private String fetchSpigotVersion() { try { - HttpURLConnection con = (HttpURLConnection) new URL("https://www.spigotmc.org/api/general.php") - .openConnection(); + // We're connecting to spigot's API + URL url = new URL("https://www.spigotmc.org/api/general.php"); + // Creating a connection + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + // We're writing a body that contains the API access key (Not required and obsolete, but!) con.setDoOutput(true); - con.setRequestMethod("POST"); - con.getOutputStream() - .write(("key=98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4&resource=32453") - .getBytes("UTF-8")); - String version = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine(); - if (version.length() <= 10) { - return version; + + // Can't think of a clean way to represent this without looking bad + String body = "key" + "=" + "98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4" + "&" + + "resource=" + this.resourceID; + + // Get the output stream, what the site receives + try (OutputStream stream = con.getOutputStream()) { + // Write our body containing version and access key + stream.write(body.getBytes(StandardCharsets.UTF_8)); + } + + // Get the input stream, what we receive + try (InputStream input = con.getInputStream()) { + // Read it to string + String version = IOUtils.toString(input); + + // If the version is not empty, return it + if (!version.isEmpty()) { + return version; + } } } catch (Exception ex) { @@ -56,12 +107,62 @@ public class UpdateChecker { return null; } - private String toReadable(String version) { - String[] split = Pattern.compile(".", Pattern.LITERAL).split(version.replace("v", "")); - version = ""; - for (String s : split) { - version += String.format("%4s", s); + private boolean isNewerVersion(String currentVersion, String newVersion) { + // Remove 'v' from string, split by decimal points + String[] cSplit = currentVersion.replace("v", "").split("\\."); + String[] nSplit = newVersion.replace("v", "").split("\\."); + + // Iterate over the versions from left to right + for (int i = 0; i < Math.max(cSplit.length, nSplit.length); i++) { + // If the current version doesn't have the next version, then it's older + if (cSplit.length <= i) { + return true; + } else if (nSplit.length <= i) { + // If the new version doesn't have the next version, then it's older + return false; + } + + // String compare the versions, should perform the same as an int compare + int compareResult = cSplit[i].compareTo(nSplit[i]); + + // Same version + if (compareResult == 0) { + continue; + } + + // Return if current version is inferior to new versio + return compareResult < 0; } - return version; + + // Both versions should be the same, return false as it's not a newer version + return false; + } + + /** + * Fetches from jenkins, using the REST api the last snapshot build information + */ + private Map fetchLastSnapshotBuild() { + try { + // We're connecting to md_5's jenkins REST api + URL url = new URL("https://ci.md-5.net/job/LibsDisguises/lastSuccessfulBuild/api/json"); + // Creating a connection + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + Map jsonObject; + + // Get the input stream, what we receive + try (InputStream input = con.getInputStream()) { + // Read it to string + String json = IOUtils.toString(input); + + jsonObject = new Gson().fromJson(json, Map.class); + } + + return jsonObject; + } + catch (Exception ex) { + DisguiseUtilities.getLogger().warning("Failed to check for a snapshot update on jenkins."); + } + + return null; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index d5f6e6a0..bbafb99b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -72,6 +72,12 @@ NotifyUpdate: true # Whats the permission to get the notification? Permission: 'libsdisguises.update' +# Where should the plugin check for updates? +# SAME_BUILDS - Will check snapshots if you're not using a release build +# RELEASES - Only check for actual releases +# SNAPSHOTS - Only check for new snapshots +UpdatesBranch: SAME_BUILDS + # Whats the max size allowed for command disguiseradius DisguiseRadiusMax: 50 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 14e448eb..92a9b8c6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,9 +2,11 @@ name: LibsDisguises main: me.libraryaddict.disguise.LibsDisguises description: A disguise plugin with various disguises. version: ${project.version} +build-number: ${build.number} author: libraryaddict authors: [Byteflux, Navid K.] depend: [ProtocolLib] +api-version: 1.13 commands: libsdisguises: permission: libsdisguises.seecmd.libsdisguises @@ -128,6 +130,4 @@ permissions: libsdisguises.seecmd.disguisemodifyradius: description: See the /disguisemodifyradius command in tab-completion libsdisguises.seecmd.disguisemodifyentity: - description: See the /disguisemodifyentity command in tab-completion - -api-version: 1.13 \ No newline at end of file + description: See the /disguisemodifyentity command in tab-completion \ No newline at end of file