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

This commit is contained in:
libraryaddict 2018-12-16 14:47:42 +13:00
parent add91b6705
commit 5a8d39a3a0
12 changed files with 352 additions and 108 deletions

View File

@ -4,7 +4,7 @@
<!-- A good example on why temporary names for project identification shouldn't be used --> <!-- A good example on why temporary names for project identification shouldn't be used -->
<groupId>LibsDisguises</groupId> <groupId>LibsDisguises</groupId>
<artifactId>LibsDisguises</artifactId> <artifactId>LibsDisguises</artifactId>
<version>9.7.0</version> <version>9.7.0-SNAPSHOT</version>
<build> <build>
<defaultGoal>clean install</defaultGoal> <defaultGoal>clean install</defaultGoal>
@ -35,6 +35,7 @@
<properties> <properties>
<build.number>unknown</build.number>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

View File

@ -22,6 +22,12 @@ public class DisguiseConfig {
CREATE_SCOREBOARD; CREATE_SCOREBOARD;
} }
public enum UpdatesBranch {
SAME_BUILDS,
SNAPSHOTS,
RELEASES
}
private static boolean animationEnabled; private static boolean animationEnabled;
private static boolean bedEnabled; private static boolean bedEnabled;
private static boolean blowDisguisesWhenAttacking; private static boolean blowDisguisesWhenAttacking;
@ -69,6 +75,15 @@ public class DisguiseConfig {
private static boolean explicitDisguisePermissions; private static boolean explicitDisguisePermissions;
private static boolean disableCommands; private static boolean disableCommands;
private static int uuidGeneratedVersion; 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() { public static int getUUIDGeneratedVersion() {
return uuidGeneratedVersion; return uuidGeneratedVersion;
@ -260,6 +275,14 @@ public class DisguiseConfig {
DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!"); 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 { try {
String option = config.getString("SelfDisguisesScoreboard", DisguisePushing.MODIFY_SCOREBOARD.name()) String option = config.getString("SelfDisguisesScoreboard", DisguisePushing.MODIFY_SCOREBOARD.name())
.toUpperCase(); .toUpperCase();
@ -270,7 +293,7 @@ public class DisguiseConfig {
disablePushing = DisguisePushing.valueOf(option); disablePushing = DisguisePushing.valueOf(option);
} }
catch (Exception ex) { 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"); "' to a valid option for SelfDisguisesTeam");
} }

View File

@ -23,6 +23,7 @@ import me.libraryaddict.disguise.utilities.parser.DisguisePermissions;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -47,60 +48,23 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.TimeUnit;
public class DisguiseListener implements Listener { public class DisguiseListener implements Listener {
private String currentVersion; private String currentVersion;
private HashMap<String, Boolean[]> disguiseClone = new HashMap<>(); private HashMap<String, Boolean[]> disguiseClone = new HashMap<>();
private HashMap<String, Disguise> disguiseEntity = new HashMap<>(); private HashMap<String, Disguise> disguiseEntity = new HashMap<>();
private HashMap<String, String[]> disguiseModify = new HashMap<>(); private HashMap<String, String[]> disguiseModify = new HashMap<>();
private HashMap<String, BukkitRunnable> disguiseRunnable = new HashMap<>(); private HashMap<String, BukkitRunnable> disguiseRunnable = new HashMap<>();
private String latestVersion; private String latestVersion;
private LibsMsg updateMessage;
private LibsDisguises plugin; private LibsDisguises plugin;
private BukkitTask updaterTask; private BukkitTask updaterTask;
public DisguiseListener(LibsDisguises libsDisguises) { public DisguiseListener(LibsDisguises libsDisguises) {
plugin = libsDisguises; plugin = libsDisguises;
if (plugin.getConfig().getBoolean("NotifyUpdate")) { runUpdateScheduler();
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
}
if (!DisguiseConfig.isSaveEntityDisguises()) if (!DisguiseConfig.isSaveEntityDisguises())
return; 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() { public void cleanup() {
for (BukkitRunnable r : disguiseRunnable.values()) { for (BukkitRunnable r : disguiseRunnable.values()) {
r.cancel(); r.cancel();
@ -284,9 +332,7 @@ public class DisguiseListener implements Listener {
public void onJoin(PlayerJoinEvent event) { public void onJoin(PlayerJoinEvent event) {
Player p = event.getPlayer(); Player p = event.getPlayer();
if (latestVersion != null && p.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) { notifyUpdate(p);
p.sendMessage(LibsMsg.UPDATE_READY.get(currentVersion, latestVersion));
}
if (DisguiseConfig.isBedPacketsEnabled()) { if (DisguiseConfig.isBedPacketsEnabled()) {
chunkMove(p, p.getLocation(), null); chunkMove(p, p.getLocation(), null);

View File

@ -13,6 +13,7 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter; import org.bukkit.command.TabCompleter;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.*; import org.bukkit.entity.*;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@ -27,23 +28,32 @@ import java.util.HashSet;
public class LibsDisguises extends JavaPlugin { public class LibsDisguises extends JavaPlugin {
private static LibsDisguises instance; private static LibsDisguises instance;
private DisguiseListener listener; private DisguiseListener listener;
private String buildNumber;
@Override @Override
public void onEnable() { public void onEnable() {
instance = this; instance = this;
getLogger().info("Discovered nms version: " + ReflectionManager.getBukkitVersion());
if (!new File(getDataFolder(), "disguises.yml").exists()) { if (!new File(getDataFolder(), "disguises.yml").exists()) {
saveResource("disguises.yml", false); 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()); LibsPremium.check(getDescription().getVersion());
if (ReflectionManager.getMinecraftVersion().startsWith("1.13")) { if (ReflectionManager.getMinecraftVersion().startsWith("1.13")) {
if (!LibsPremium.isPremium()) { if (!LibsPremium.isPremium()) {
getLogger().severe("You must purchase the plugin to use 1.13!"); 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 " + getLogger().severe("If you've already purchased the plugin, place the purchased jar inside the " +
"Lib's Disguises plugin folder"); "Lib's Disguises plugin folder");
getPluginLoader().disablePlugin(this); getPluginLoader().disablePlugin(this);
@ -92,8 +102,25 @@ public class LibsDisguises extends JavaPlugin {
infectWithMetrics(); infectWithMetrics();
} }
@Override
public void onDisable() {
DisguiseUtilities.saveDisguises();
for (Player player : Bukkit.getOnlinePlayers()) {
DisguiseUtilities.removeSelfDisguiseScoreboard(player);
}
}
private void infectWithMetrics() { 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() ? final String premium = LibsPremium.isPremium() ?
getDescription().getVersion().contains("SNAPSHOT") ? "Paid Builds" : "Paid Plugin" : "Free Builds"; 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") { metrics.addCustomChart(new Metrics.SimplePie("commands") {
@Override @Override
public String getValue() { 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") { 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 * 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 boolean isReleaseBuild() {
public void onDisable() { return !getDescription().getVersion().contains("-SNAPSHOT");
DisguiseUtilities.saveDisguises(); }
for (Player player : Bukkit.getOnlinePlayers()) { public String getBuildNo() {
DisguiseUtilities.removeSelfDisguiseScoreboard(player); return buildNumber;
}
} }
private void registerCommand(String commandName, CommandExecutor executioner) { private void registerCommand(String commandName, CommandExecutor executioner) {

View File

@ -1,9 +1,9 @@
package me.libraryaddict.disguise.commands; package me.libraryaddict.disguise.commands;
import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.LibsDisguises;
import me.libraryaddict.disguise.utilities.LibsMsg; import me.libraryaddict.disguise.utilities.LibsMsg;
import me.libraryaddict.disguise.utilities.LibsPremium; import me.libraryaddict.disguise.utilities.LibsPremium;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -52,9 +52,16 @@ public class LibsDisguisesCommand implements CommandExecutor, TabCompleter {
@Override @Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (args.length == 0) { if (args.length == 0) {
sender.sendMessage(ChatColor.DARK_GREEN + "This server is running " + "Lib's Disguises v" + LibsDisguises disguises = LibsDisguises.getInstance();
Bukkit.getPluginManager().getPlugin("LibsDisguises").getDescription().getVersion() +
" by libraryaddict, formerly maintained " + "by Byteflux and NavidK0." + 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") ? (sender.hasPermission("libsdisguises.reload") ?
"\nUse " + ChatColor.GREEN + "/libsdisguises " + "reload" + ChatColor.DARK_GREEN + "\nUse " + ChatColor.GREEN + "/libsdisguises " + "reload" + ChatColor.DARK_GREEN +
" to reload the config. All disguises will be blown by doing this" + "." : "")); " to reload the config. All disguises will be blown by doing this" + "." : ""));

View File

@ -167,7 +167,11 @@ public enum LibsMsg {
UNDISRADIUS(ChatColor.RED + "Successfully undisguised %s entities!"), UNDISRADIUS(ChatColor.RED + "Successfully undisguised %s entities!"),
UPDATE_READY(ChatColor.RED + "[LibsDisguises] " + ChatColor.DARK_RED + 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 + "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_ON(ChatColor.GREEN + "Toggled viewing own disguise on!"),
VIEW_SELF_OFF(ChatColor.GREEN + "Toggled viewing own disguise off!"); VIEW_SELF_OFF(ChatColor.GREEN + "Toggled viewing own disguise off!");

View File

@ -1,10 +1,8 @@
package me.libraryaddict.disguise.utilities; package me.libraryaddict.disguise.utilities;
import org.apache.commons.io.IOUtils;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File; import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
@ -42,12 +40,9 @@ public class LibsPremium {
thisPluginIsPaidFor = (Boolean) m.invoke(null); thisPluginIsPaidFor = (Boolean) m.invoke(null);
String pluginVersion; String pluginVersion;
try (InputStream stream = cl.getResourceAsStream("plugin.yml")) { YamlConfiguration config = ReflectionManager.getPluginYaml(cl);
YamlConfiguration config = new YamlConfiguration();
config.loadFromString(IOUtils.toString(stream, "UTF-8"));
pluginVersion = config.getString("version"); pluginVersion = config.getString("version");
}
if (isPremium()) { if (isPremium()) {
// Found a premium Lib's Disguises jar (v5.2.6), premium enabled! // Found a premium Lib's Disguises jar (v5.2.6), premium enabled!

View File

@ -31,8 +31,8 @@ public class Metrics {
final String examplePackage = new String( final String examplePackage = new String(
new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); 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 // 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() if (Metrics.class.getPackage().getName().equals(defaultPackage) ||
.equals(examplePackage)) { Metrics.class.getPackage().getName().equals(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
} }
} }
@ -51,6 +51,8 @@ public class Metrics {
// The plugin // The plugin
private final JavaPlugin plugin; private final JavaPlugin plugin;
// The plugin version
private final String version;
// A list with all custom charts // A list with all custom charts
private final List<CustomChart> charts = new ArrayList<>(); private final List<CustomChart> charts = new ArrayList<>();
@ -60,11 +62,13 @@ public class Metrics {
* *
* @param plugin The plugin which stats should be submitted. * @param plugin The plugin which stats should be submitted.
*/ */
public Metrics(JavaPlugin plugin) { public Metrics(JavaPlugin plugin, String version) {
if (plugin == null) { if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null!"); throw new IllegalArgumentException("Plugin cannot be null!");
} }
this.plugin = plugin; this.plugin = plugin;
this.version = version;
// Get the config file // Get the config file
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
@ -83,8 +87,11 @@ public class Metrics {
// Inform the server owners about bStats // Inform the server owners about bStats
config.options() 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 :)") .header("bStats collects some data for plugin authors like how many servers are using their " +
.copyDefaults(true); "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 { try {
config.save(configFile); config.save(configFile);
} }
@ -140,8 +147,10 @@ public class Metrics {
timer.cancel(); timer.cancel();
return; return;
} }
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) // 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() { Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
@ -165,10 +174,9 @@ public class Metrics {
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
String pluginName = plugin.getDescription().getName(); String pluginName = plugin.getDescription().getName();
String pluginVersion = plugin.getDescription().getVersion();
data.put("pluginName", pluginName); // Append the name of the plugin 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(); JSONArray customCharts = new JSONArray();
for (CustomChart customChart : charts) { for (CustomChart customChart : charts) {
// Add the data of the custom charts // Add the data of the custom charts

View File

@ -8,12 +8,17 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObje
import com.comphenix.protocol.wrappers.nbt.NbtWrapper; import com.comphenix.protocol.wrappers.nbt.NbtWrapper;
import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import org.apache.commons.io.IOUtils;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.*; import org.bukkit.entity.*;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Optional; import java.util.Optional;
@ -80,6 +85,20 @@ public class ReflectionManager {
entityCountField.setAccessible(true); 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() { public static int getNewEntityId() {
return getNewEntityId(true); return getNewEntityId(true);
} }

View File

@ -1,29 +1,60 @@
package me.libraryaddict.disguise.utilities; package me.libraryaddict.disguise.utilities;
import java.io.BufferedReader; import com.google.gson.Gson;
import java.io.InputStreamReader; import org.apache.commons.io.IOUtils;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; 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 { public class UpdateChecker {
private final String resourceID;
private String latestVersion; private String latestVersion;
private int latestSnapshot;
private boolean checkHigher(String currentVersion, String newVersion) { public UpdateChecker(String resourceID) {
String current = toReadable(currentVersion); this.resourceID = resourceID;
String newVers = toReadable(newVersion);
return current.compareTo(newVers) < 0;
} }
public void checkUpdate(String currentVersion) { public void checkSnapshotUpdate(int buildNumber) {
String version = getSpigotVersion(); Map<String, Object> lastBuild = fetchLastSnapshotBuild();
if (version == null) if (lastBuild == null || !lastBuild.containsKey("id") || !lastBuild.containsKey("timestamp")) {
return; 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; 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; latestVersion = version;
} }
@ -32,21 +63,41 @@ public class UpdateChecker {
return latestVersion; return latestVersion;
} }
public int getLatestSnapshot() {
return latestSnapshot;
}
/** /**
* Asks spigot for the version * Asks spigot for the version
*/ */
private String getSpigotVersion() { private String fetchSpigotVersion() {
try { try {
HttpURLConnection con = (HttpURLConnection) new URL("https://www.spigotmc.org/api/general.php") // We're connecting to spigot's API
.openConnection(); 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.setDoOutput(true);
con.setRequestMethod("POST");
con.getOutputStream() // Can't think of a clean way to represent this without looking bad
.write(("key=98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4&resource=32453") String body = "key" + "=" + "98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4" + "&" +
.getBytes("UTF-8")); "resource=" + this.resourceID;
String version = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine();
if (version.length() <= 10) { // Get the output stream, what the site receives
return version; 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) { catch (Exception ex) {
@ -56,12 +107,62 @@ public class UpdateChecker {
return null; return null;
} }
private String toReadable(String version) { private boolean isNewerVersion(String currentVersion, String newVersion) {
String[] split = Pattern.compile(".", Pattern.LITERAL).split(version.replace("v", "")); // Remove 'v' from string, split by decimal points
version = ""; String[] cSplit = currentVersion.replace("v", "").split("\\.");
for (String s : split) { String[] nSplit = newVersion.replace("v", "").split("\\.");
version += String.format("%4s", s);
// 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<String, Object> 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<String, Object> 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;
} }
} }

View File

@ -72,6 +72,12 @@ NotifyUpdate: true
# Whats the permission to get the notification? # Whats the permission to get the notification?
Permission: 'libsdisguises.update' 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 # Whats the max size allowed for command disguiseradius
DisguiseRadiusMax: 50 DisguiseRadiusMax: 50

View File

@ -2,9 +2,11 @@ name: LibsDisguises
main: me.libraryaddict.disguise.LibsDisguises main: me.libraryaddict.disguise.LibsDisguises
description: A disguise plugin with various disguises. description: A disguise plugin with various disguises.
version: ${project.version} version: ${project.version}
build-number: ${build.number}
author: libraryaddict author: libraryaddict
authors: [Byteflux, Navid K.] authors: [Byteflux, Navid K.]
depend: [ProtocolLib] depend: [ProtocolLib]
api-version: 1.13
commands: commands:
libsdisguises: libsdisguises:
permission: libsdisguises.seecmd.libsdisguises permission: libsdisguises.seecmd.libsdisguises
@ -129,5 +131,3 @@ permissions:
description: See the /disguisemodifyradius command in tab-completion description: See the /disguisemodifyradius command in tab-completion
libsdisguises.seecmd.disguisemodifyentity: libsdisguises.seecmd.disguisemodifyentity:
description: See the /disguisemodifyentity command in tab-completion description: See the /disguisemodifyentity command in tab-completion
api-version: 1.13