diff --git a/bin/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.class b/bin/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.class index efa6ddd..fa53fbd 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.class and b/bin/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/MainClass/MainClass.class b/bin/dev/minecraftdorado/BlackMarket/MainClass/MainClass.class index 83c340b..7af88fe 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/MainClass/MainClass.class and b/bin/dev/minecraftdorado/BlackMarket/MainClass/MainClass.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.class b/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.class index 462f046..282d0c9 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.class b/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.class index 4775800..46406a2 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial$PotionBase.class b/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial$PotionBase.class index b05d517..57e8bb0 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial$PotionBase.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial$PotionBase.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.class b/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.class index deb314d..f6eefc7 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UPotion.class b/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UPotion.class index c7747c6..530dc66 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UPotion.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UPotion.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem$Status.class b/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem$Status.class index 80d1917..8be2eea 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem$Status.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem$Status.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.class b/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.class index 3e8ffb9..4a41c96 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/Market/Market.class b/bin/dev/minecraftdorado/BlackMarket/Utils/Market/Market.class index 3b38898..d505c87 100644 Binary files a/bin/dev/minecraftdorado/BlackMarket/Utils/Market/Market.class and b/bin/dev/minecraftdorado/BlackMarket/Utils/Market/Market.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$UpdateReason.class b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$UpdateReason.class new file mode 100644 index 0000000..aa8cef1 Binary files /dev/null and b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$UpdateReason.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$UpdateResult.class b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$UpdateResult.class new file mode 100644 index 0000000..6e3b389 Binary files /dev/null and b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$UpdateResult.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$VersionScheme.class b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$VersionScheme.class new file mode 100644 index 0000000..779fe4a Binary files /dev/null and b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker$VersionScheme.class differ diff --git a/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker.class b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker.class new file mode 100644 index 0000000..6099338 Binary files /dev/null and b/bin/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker.class differ diff --git a/plugin.yml b/plugin.yml index 51cd3c5..e758385 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,9 +1,35 @@ main: dev.minecraftdorado.BlackMarket.MainClass.MainClass name: BlackMarket author: MinecraftDorado -version: 1.1 +version: 1.11 api-version: 1.13 softdepend: [Vault] commands: sell: - bm: \ No newline at end of file + bm: + +permissions: + blackmarket.admin: + description: Allows the use of all commands + default: op + children: + blackmarket.limit.*: true + blackmarket.reload: true + blackmarket.npc: true + blackmarket.open: true + blackmarket.npc: + description: Allows the use of commands for NPCs + default: op + children: + blackmarket.setnpc: true + blackmarket.removenpc: true + blackmarket.setnpc: + description: Allows usage of the /bm setnpc command + blackmarket.removenpc: + description: Allows usage of the /bm removenpc command + blackmarket.limit: + description: Limit of published articles + blackmarket.reload: + description: Allows usage of the /bm reload command + blackmarket.open: + description: Allows usage of the /bm open command \ No newline at end of file diff --git a/resources/categories/potions.yml b/resources/categories/potions.yml index 7e95ac4..79ee9ed 100644 --- a/resources/categories/potions.yml +++ b/resources/categories/potions.yml @@ -20,5 +20,135 @@ materials: - CAULDRON - BREWING_STAND - GHAST_TEAR +- FERMENTED_SPIDER_EYE + +- LINGERING_POTION +- LINGERING_POTION_AWKWARD +- LINGERING_POTION_FIRE_RESISTANCE +- LINGERING_POTION_FIRE_RESISTANCE_EXTENDED +- LINGERING_POTION_HARMING_1 +- LINGERING_POTION_HARMING_2 +- LINGERING_POTION_HEALING_1 +- LINGERING_POTION_HEALING_2 +- LINGERING_POTION_INVISIBILITY +- LINGERING_POTION_INVISIBILITY_EXTENDED +- LINGERING_POTION_LEAPING_1 +- LINGERING_POTION_LEAPING_1_EXTENDED +- LINGERING_POTION_LEAPING_2 +- LINGERING_POTION_LUCK +- LINGERING_POTION_MUNDANE +- LINGERING_POTION_NIGHT_VISION +- LINGERING_POTION_NIGHT_VISION_EXTENDED +- LINGERING_POTION_POISON_1 +- LINGERING_POTION_POISON_1_EXTENDED +- LINGERING_POTION_POISON_2 +- LINGERING_POTION_REGENERATION_1 +- LINGERING_POTION_REGENERATION_1_EXTENDED +- LINGERING_POTION_REGENERATION_2 +- LINGERING_POTION_SLOW_FALLING +- LINGERING_POTION_SLOW_FALLING_EXTENDED +- LINGERING_POTION_SLOWNESS_1 +- LINGERING_POTION_SLOWNESS_1_EXTENDED +- LINGERING_POTION_SLOWNESS_2 +- LINGERING_POTION_STRENGTH_1 +- LINGERING_POTION_STRENGTH_1_EXTENDED +- LINGERING_POTION_STRENGTH_2 +- LINGERING_POTION_SWIFTNESS_1 +- LINGERING_POTION_SWIFTNESS_1_EXTENDED +- LINGERING_POTION_SWIFTNESS_2 +- LINGERING_POTION_THICK +- LINGERING_POTION_TURTLE_MASTER_1 +- LINGERING_POTION_TURTLE_MASTER_1_EXTENDED +- LINGERING_POTION_TURTLE_MASTER_2 +- LINGERING_POTION_WATER +- LINGERING_POTION_WATER_BREATHING +- LINGERING_POTION_WATER_BREATHING_EXTENDED +- LINGERING_POTION_WEAKNESS +- LINGERING_POTION_WEAKNESS_EXTENDED + - POTION -- FERMENTED_SPIDER_EYE \ No newline at end of file +- POTION_AWKWARD +- POTION_FIRE_RESISTANCE +- POTION_FIRE_RESISTANCE_EXTENDED +- POTION_HARMING_1 +- POTION_HARMING_2 +- POTION_HEALING_1 +- POTION_HEALING_2 +- POTION_INVISIBILITY_EXTENDED +- POTION_LEAPING_1 +- POTION_LEAPING_1_EXTENDED +- POTION_LEAPING_2 +- POTION_LUCK +- POTION_MUNDANE +- POTION_NIGHT_VISION +- POTION_NIGHT_VISION_EXTENDED +- POTION_POISON_1 +- POTION_POISON_1_EXTENDED +- POTION_POISON_2 +- POTION_REGENERATION_1 +- POTION_REGENERATION_1_EXTENDED +- POTION_REGENERATION_2 +- POTION_SLOW_FALLING +- POTION_SLOW_FALLING_EXTENDED +- POTION_SLOWNESS_1 +- POTION_SLOWNESS_1_EXTENDED +- POTION_SLOWNESS_2 +- POTION_STRENGTH_1 +- POTION_STRENGTH_1_EXTENDED +- POTION_STRENGTH_2 +- POTION_SWIFTNESS_1 +- POTION_SWIFTNESS_1_EXTENDED +- POTION_SWIFTNESS_2 +- POTION_THICK +- POTION_TURTLE_MASTER_1 +- POTION_TURTLE_MASTER_1_EXTENDED +- POTION_TURTLE_MASTER_2 +- POTION_WATER +- POTION_WATER_BREATHING +- POTION_WATER_BREATHING_EXTENDED +- POTION_WEAKNESS +- POTION_WEAKNESS_EXTENDED +- +- SPLASH_POTION +- SPLASH_POTION_AWKWARD +- SPLASH_POTION_FIRE_RESISTANCE +- SPLASH_POTION_FIRE_RESISTANCE_EXTENDED +- SPLASH_POTION_HARMING_1 +- SPLASH_POTION_HARMING_2 +- SPLASH_POTION_HEALING_1 +- SPLASH_POTION_HEALING_2 +- SPLASH_POTION_INVISIBILITY +- SPLASH_POTION_INVISIBILITY_EXTENDED +- SPLASH_POTION_LEAPING_1 +- SPLASH_POTION_LEAPING_1_EXTENDED +- SPLASH_POTION_LEAPING_2 +- SPLASH_POTION_LUCK +- SPLASH_POTION_MUNDANE +- SPLASH_POTION_NIGHT_VISION +- SPLASH_POTION_NIGHT_VISION_EXTENDED +- SPLASH_POTION_POISON_1 +- SPLASH_POTION_POISON_1_EXTENDED +- SPLASH_POTION_POISON_2 +- SPLASH_POTION_REGENERATION_1 +- SPLASH_POTION_REGENERATION_1_EXTENDED +- SPLASH_POTION_REGENERATION_2 +- SPLASH_POTION_SLOW_FALLING +- SPLASH_POTION_SLOW_FALLING_EXTENDED +- SPLASH_POTION_SLOWNESS_1 +- SPLASH_POTION_SLOWNESS_1_EXTENDED +- SPLASH_POTION_SLOWNESS_2 +- SPLASH_POTION_STRENGTH_1 +- SPLASH_POTION_STRENGTH_1_EXTENDED +- SPLASH_POTION_STRENGTH_2 +- SPLASH_POTION_SWIFTNESS_1 +- SPLASH_POTION_SWIFTNESS_1_EXTENDED +- SPLASH_POTION_SWIFTNESS_2 +- SPLASH_POTION_THICK +- SPLASH_POTION_TURTLE_MASTER_1 +- SPLASH_POTION_TURTLE_MASTER_1_EXTENDED +- SPLASH_POTION_TURTLE_MASTER_2 +- SPLASH_POTION_WATER +- SPLASH_POTION_WATER_BREATHING +- SPLASH_POTION_WATER_BREATHING_EXTENDED +- SPLASH_POTION_WEAKNESS +- SPLASH_POTION_WEAKNESS_EXTENDED \ No newline at end of file diff --git a/src/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.java b/src/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.java index 2acc543..0583fb9 100644 --- a/src/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.java +++ b/src/dev/minecraftdorado/BlackMarket/Listeners/PlayerListener.java @@ -13,6 +13,8 @@ import dev.minecraftdorado.BlackMarket.MainClass.MainClass; import dev.minecraftdorado.BlackMarket.Utils.Config; +import dev.minecraftdorado.BlackMarket.Utils.UpdateChecker; +import dev.minecraftdorado.BlackMarket.Utils.UpdateChecker.UpdateReason; import dev.minecraftdorado.BlackMarket.Utils.Entities.NPC.Events.NPCInteractEvent; import dev.minecraftdorado.BlackMarket.Utils.Inventory.InventoryManager; import dev.minecraftdorado.BlackMarket.Utils.Market.Market; @@ -28,7 +30,26 @@ public class PlayerListener implements Listener { */ @EventHandler - private void join(PlayerJoinEvent e) {PacketReader.get(e.getPlayer()).inject();} + private void join(PlayerJoinEvent e) { + PacketReader.get(e.getPlayer()).inject(); + + if(e.getPlayer().hasPermission("blackmarket.admin")) + UpdateChecker.init(MainClass.main, 79819).requestUpdateCheck().whenComplete((result, ee) -> { + if (result.requiresUpdate()) { + e.getPlayer().sendMessage("§6[BlackMarket] §7» " + String.format("An update is available! BlackMarket %s may be downloaded on SpigotMC", result.getNewestVersion())); + return; + } + + UpdateReason reason = result.getReason(); + if (reason == UpdateReason.UP_TO_DATE) + e.getPlayer().sendMessage("§6[BlackMarket] §7» " + String.format("Your version of BlackMarket (%s) is up to date!", result.getNewestVersion())); + else if (reason == UpdateReason.UNRELEASED_VERSION) + e.getPlayer().sendMessage("§6[BlackMarket] §7» " + String.format("Your version of BlackMarket (%s) is more recent than the one publicly available. Are you on a development build?", result.getNewestVersion())); + else + e.getPlayer().sendMessage("§6[BlackMarket] §7» " + "Could not check for a new version of BlackMarket. Reason: " + reason); + } + ); + } /* * Uninject PacketReader diff --git a/src/dev/minecraftdorado/BlackMarket/MainClass/MainClass.java b/src/dev/minecraftdorado/BlackMarket/MainClass/MainClass.java index eeaace6..96b0a6c 100644 --- a/src/dev/minecraftdorado/BlackMarket/MainClass/MainClass.java +++ b/src/dev/minecraftdorado/BlackMarket/MainClass/MainClass.java @@ -12,6 +12,8 @@ import dev.minecraftdorado.BlackMarket.Utils.Packets.PacketReader; import net.milkbowl.vault.economy.Economy; import dev.minecraftdorado.BlackMarket.Utils.Config; +import dev.minecraftdorado.BlackMarket.Utils.UpdateChecker; +import dev.minecraftdorado.BlackMarket.Utils.UpdateChecker.UpdateReason; import dev.minecraftdorado.BlackMarket.Utils.Entities.Hologram.HologramManager; import dev.minecraftdorado.BlackMarket.Utils.Entities.NPC.NPCManager; import dev.minecraftdorado.BlackMarket.Utils.Entities.NPC.Skins.SkinData; @@ -38,6 +40,22 @@ public void onEnable() { return; } + UpdateChecker.init(this, 85558).requestUpdateCheck().whenComplete((result, e) -> { + if (result.requiresUpdate()) { + this.getLogger().info(String.format("An update is available! BlackMarket %s may be downloaded on SpigotMC", result.getNewestVersion())); + return; + } + + UpdateReason reason = result.getReason(); + if (reason == UpdateReason.UP_TO_DATE) + this.getLogger().info(String.format("Your version of BlackMarket (%s) is up to date!", result.getNewestVersion())); + else if (reason == UpdateReason.UNRELEASED_VERSION) + this.getLogger().info(String.format("Your version of BlackMarket (%s) is more recent than the one publicly available. Are you on a development build?", result.getNewestVersion())); + else + this.getLogger().warning("Could not check for a new version of BlackMarket. Reason: " + reason); + } + ); + getServer().getPluginCommand("sell").setExecutor(new sell()); getServer().getPluginCommand("bm").setExecutor(new bm()); getServer().getPluginCommand("bm").setTabCompleter(new bmTab()); diff --git a/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.java b/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.java index b7e9d07..1b80543 100644 --- a/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.java +++ b/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/MySQL.java @@ -68,8 +68,8 @@ public void createTables(URL url){ statement.close(); } }catch(Exception ex){ - MainClass.main.getLogger().severe(String.format("» MySQL can't create the table: " + url.toString(), MainClass.main.getDescription().getName())); - ex.printStackTrace(); + String[] s = url.toString().split("/"); + MainClass.main.getLogger().severe(String.format("» MySQL can't create the table or already exist: " + s[s.length-1], MainClass.main.getDescription().getName())); } } } \ No newline at end of file diff --git a/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.java b/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.java index d17451a..b52e6e3 100644 --- a/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.java +++ b/src/dev/minecraftdorado/BlackMarket/Utils/DataBase/MySQL/dbMySQL.java @@ -48,11 +48,7 @@ public static void load() { public static void save() { for(Data data : PlayerData.list.values()) for(BlackItem bItem : data.getItems()) - try { - addBlackItem(bItem); - } catch (SQLException e) { - e.printStackTrace(); - } + updateStatus(bItem); } private static void loadBlackItems() throws SQLException { @@ -87,8 +83,10 @@ private static void loadBlackItems() throws SQLException { } } - private static void updateStatus(BlackItem bItem) throws SQLException { - if(con == null || con.isClosed()) con = sql.getConnection(); + public static void updateStatus(BlackItem bItem) { + try { + if(con == null || con.isClosed()) con = sql.getConnection(); + } catch(Exception e) {e.printStackTrace();} try { PreparedStatement preparedStatement = null; @@ -105,8 +103,10 @@ private static void updateStatus(BlackItem bItem) throws SQLException { } } - private static void addBlackItem(BlackItem bItem) throws SQLException { - if(con == null || con.isClosed()) con = sql.getConnection(); + public static void addBlackItem(BlackItem bItem) { + try { + if(con == null || con.isClosed()) con = sql.getConnection(); + } catch(Exception e) {e.printStackTrace();} try { PreparedStatement preparedStatement = null; @@ -121,6 +121,7 @@ private static void addBlackItem(BlackItem bItem) throws SQLException { updateStatus(bItem); return; } + resultSet.close(); preparedStatement.close(); queryBuilder = new StringBuilder(); diff --git a/src/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.java b/src/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.java index 748a324..0ee9841 100644 --- a/src/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.java +++ b/src/dev/minecraftdorado/BlackMarket/Utils/Inventory/Utils/UMaterial.java @@ -1567,7 +1567,9 @@ public static UMaterial matchPotion(ItemStack potion) { : a : null; if(type != null) { final String g = base + type + (max != 1 && l <= max ? "_" + l : "") + (extended ? "_EXTENDED" : ""); - return valueOf(g); + try { + return valueOf(g); + }catch(Exception e) {return valueOf(g + "_1");} } else { return UMaterial.POTION; } diff --git a/src/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.java b/src/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.java index f4fd32c..676e74b 100644 --- a/src/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.java +++ b/src/dev/minecraftdorado/BlackMarket/Utils/Market/BlackItem.java @@ -14,6 +14,8 @@ import dev.minecraftdorado.BlackMarket.Utils.Config; import dev.minecraftdorado.BlackMarket.Utils.Utils; +import dev.minecraftdorado.BlackMarket.Utils.DataBase.MySQL.dbMySQL; +import dev.minecraftdorado.BlackMarket.Utils.Config.StorageType; public class BlackItem { @@ -49,6 +51,7 @@ public BlackItem(ItemStack item, double value, UUID owner) { cal.setTime(new Date()); cal.add(Calendar.MINUTE, Config.getExpiredTime()); this.date = cal.getTime(); + dbMySQL.addBlackItem(this); } public int getId() { @@ -91,13 +94,15 @@ public UUID getOwner() { public Status getStatus() { if(status.equals(Status.ON_SALE)) { if(Duration.between(new Date().toInstant(), date.toInstant()).getSeconds() <= 0) - status = Status.TIME_OUT; + setStatus(Status.TIME_OUT); } return status; } public void setStatus(Status status) { this.status = status; + if(Config.getStorageType().equals(StorageType.MySQL)) + dbMySQL.updateStatus(this); } public enum Status { diff --git a/src/dev/minecraftdorado/BlackMarket/Utils/Market/Market.java b/src/dev/minecraftdorado/BlackMarket/Utils/Market/Market.java index c1cf617..3b9bc5e 100644 --- a/src/dev/minecraftdorado/BlackMarket/Utils/Market/Market.java +++ b/src/dev/minecraftdorado/BlackMarket/Utils/Market/Market.java @@ -128,7 +128,7 @@ public static Inv getMarketInventory(Player player) { for(BlackItem bItem : list.values()) { if(bItem.getStatus().equals(Status.ON_SALE)) { - if(category == null || category.getMaterials().isEmpty() || category.getMaterials().contains(UMaterial.match(bItem.getItemStack()))) + if(category == null || category.getMaterials().isEmpty() || category.contain(UMaterial.match(bItem.getItemStack()))) l.add(bItem); }else toRemove.add(bItem.getId()); diff --git a/src/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker.java b/src/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker.java new file mode 100644 index 0000000..dcc4b5b --- /dev/null +++ b/src/dev/minecraftdorado/BlackMarket/Utils/UpdateChecker.java @@ -0,0 +1,176 @@ +package dev.minecraftdorado.BlackMarket.Utils; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.google.common.base.Preconditions; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +import org.apache.commons.lang.math.NumberUtils; +import org.bukkit.plugin.java.JavaPlugin; + +public final class UpdateChecker { + + public static final VersionScheme VERSION_SCHEME_DECIMAL = (first, second) -> { + String[] firstSplit = splitVersionInfo(first), secondSplit = splitVersionInfo(second); + if (firstSplit == null || secondSplit == null) return null; + + for (int i = 0; i < Math.min(firstSplit.length, secondSplit.length); i++) { + int currentValue = NumberUtils.toInt(firstSplit[i]), newestValue = NumberUtils.toInt(secondSplit[i]); + + if (newestValue > currentValue) { + return second; + } else if (newestValue < currentValue) { + return first; + } + } + + return (secondSplit.length > firstSplit.length) ? second : first; + }; + + private static final String USER_AGENT = "CHOCO-update-checker"; + private static final String UPDATE_URL = "https://api.spigotmc.org/simple/0.1/index.php?action=getResource&id=%d"; + private static final Pattern DECIMAL_SCHEME_PATTERN = Pattern.compile("\\d+(?:\\.\\d+)*"); + + private static UpdateChecker instance; + + private UpdateResult lastResult = null; + + private final JavaPlugin plugin; + private final int pluginID; + private final VersionScheme versionScheme; + + private UpdateChecker(JavaPlugin plugin, int pluginID, VersionScheme versionScheme) { + this.plugin = plugin; + this.pluginID = pluginID; + this.versionScheme = versionScheme; + } + + public CompletableFuture requestUpdateCheck() { + return CompletableFuture.supplyAsync(() -> { + int responseCode = -1; + try { + URL url = new URL(String.format(UPDATE_URL, pluginID)); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.addRequestProperty("User-Agent", USER_AGENT); + + InputStreamReader reader = new InputStreamReader(connection.getInputStream()); + responseCode = connection.getResponseCode(); + + JsonElement element = new JsonParser().parse(reader); + reader.close(); + + JsonObject versionObject = element.getAsJsonObject(); + String current = plugin.getDescription().getVersion(), newest = versionObject.get("current_version").getAsString(); + String latest = versionScheme.compareVersions(current, newest); + + if (latest == null) { + return new UpdateResult(UpdateReason.UNSUPPORTED_VERSION_SCHEME); + } else if (latest.equals(current)) { + return new UpdateResult(current.equals(newest) ? UpdateReason.UP_TO_DATE : UpdateReason.UNRELEASED_VERSION); + } else if (latest.equals(newest)) { + return new UpdateResult(UpdateReason.NEW_UPDATE, latest); + } + } catch (IOException e) { + return new UpdateResult(UpdateReason.COULD_NOT_CONNECT); + } catch (JsonSyntaxException e) { + return new UpdateResult(UpdateReason.INVALID_JSON); + } + + return new UpdateResult(responseCode == 401 ? UpdateReason.UNAUTHORIZED_QUERY : UpdateReason.UNKNOWN_ERROR); + }); + } + + public UpdateResult getLastResult() { + return lastResult; + } + + private static String[] splitVersionInfo(String version) { + Matcher matcher = DECIMAL_SCHEME_PATTERN.matcher(version); + if (!matcher.find()) return null; + + return matcher.group().split("\\."); + } + + public static UpdateChecker init(JavaPlugin plugin, int pluginID, VersionScheme versionScheme) { + Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); + Preconditions.checkArgument(pluginID > 0, "Plugin ID must be greater than 0"); + Preconditions.checkArgument(versionScheme != null, "null version schemes are unsupported"); + + return (instance == null) ? instance = new UpdateChecker(plugin, pluginID, versionScheme) : instance; + } + + public static UpdateChecker init(JavaPlugin plugin, int pluginID) { + return init(plugin, pluginID, VERSION_SCHEME_DECIMAL); + } + + public static UpdateChecker get() { + Preconditions.checkState(instance != null, "Instance has not yet been initialized. Be sure #init() has been invoked"); + return instance; + } + + public static boolean isInitialized() { + return instance != null; + } + + @FunctionalInterface + public static interface VersionScheme { + + public String compareVersions(String first, String second); + + } + + public static enum UpdateReason { + NEW_UPDATE, // The only reason that requires an update + COULD_NOT_CONNECT, + INVALID_JSON, + UNAUTHORIZED_QUERY, + UNRELEASED_VERSION, + UNKNOWN_ERROR, + UNSUPPORTED_VERSION_SCHEME, + UP_TO_DATE; + } + + public final class UpdateResult { + + private final UpdateReason reason; + private final String newestVersion; + + { // An actual use for initializer blocks. This is madness! + UpdateChecker.this.lastResult = this; + } + + private UpdateResult(UpdateReason reason, String newestVersion) { + this.reason = reason; + this.newestVersion = newestVersion; + } + + private UpdateResult(UpdateReason reason) { + Preconditions.checkArgument(reason != UpdateReason.NEW_UPDATE, "Reasons that require updates must also provide the latest version String"); + this.reason = reason; + this.newestVersion = plugin.getDescription().getVersion(); + } + + public UpdateReason getReason() { + return reason; + } + + public boolean requiresUpdate() { + return reason == UpdateReason.NEW_UPDATE; + } + + public String getNewestVersion() { + return newestVersion; + } + + } + +} \ No newline at end of file