From 3f7f86ef67c5750abb53b38249d980eb6a6f22c4 Mon Sep 17 00:00:00 2001 From: thomas Date: Mon, 9 Aug 2021 02:26:23 +0200 Subject: [PATCH] Custom command support, added global status --- pom.xml | 6 +- .../java/nl/iobyte/themepark/ThemePark.java | 8 +- .../api/attraction/enums/Status.java | 1 + .../api/config/enums/StorageKey.java | 5 +- .../api/load/objects/StatusDataLoader.java | 2 +- .../themepark/commands/ThemeParkCommand.java | 32 +- .../themepark/listeners/PlayerListener.java | 3 + .../iobyte/themepark/utils/UpdateManager.java | 312 ++++++++++++++++++ src/main/resources/menu.yml | 2 +- src/main/resources/plugin.yml | 7 +- src/main/resources/settings.yml | 4 +- themepark.iml | 9 +- 12 files changed, 366 insertions(+), 25 deletions(-) create mode 100644 src/main/java/nl/iobyte/themepark/utils/UpdateManager.java diff --git a/pom.xml b/pom.xml index 5b5c949..ba54534 100644 --- a/pom.xml +++ b/pom.xml @@ -57,7 +57,7 @@ com.zaxxer HikariCP - 4.0.3 + 5.0.0 me.clip @@ -73,7 +73,7 @@ net.minidev json-smart - 1.1.1 + 2.4.7 com.bergerkiller.bukkit @@ -90,7 +90,7 @@ com.github.cryptomorin XSeries - 8.1.0 + 8.2.0 com.sk89q.worldguard diff --git a/src/main/java/nl/iobyte/themepark/ThemePark.java b/src/main/java/nl/iobyte/themepark/ThemePark.java index 8d1f924..df96c41 100644 --- a/src/main/java/nl/iobyte/themepark/ThemePark.java +++ b/src/main/java/nl/iobyte/themepark/ThemePark.java @@ -4,6 +4,7 @@ import nl.iobyte.menuapi.MenuAPI; import nl.iobyte.themepark.api.ThemeParkAPI; import nl.iobyte.themepark.commands.ThemeParkCommand; import nl.iobyte.themepark.listeners.*; +import nl.iobyte.themepark.utils.UpdateManager; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; @@ -22,6 +23,7 @@ public class ThemePark extends JavaPlugin { loadCommands(); loadListeners(); loadTrainCarts(); + loadUpdateManager(); } private void loadCommands() { @@ -47,13 +49,17 @@ public class ThemePark extends JavaPlugin { Class clazz = Class.forName("com.bergerkiller.bukkit.tc.signactions.SignAction"); Class sign = Class.forName("nl.iobyte.themepark.traincarts.RideCountSign"); Method method = clazz.getMethod("register", clazz); - method.invoke(clazz, sign.newInstance()); + method.invoke(clazz, sign.getDeclaredConstructor().newInstance()); } } catch (Exception e) { System.out.println("["+getName()+"] Unable to hook into TrainCarts"); } } + private void loadUpdateManager() { + //TODO new UpdateManager(this, 48648); + } + public void onDisable() { disabling = true; api.disable(); diff --git a/src/main/java/nl/iobyte/themepark/api/attraction/enums/Status.java b/src/main/java/nl/iobyte/themepark/api/attraction/enums/Status.java index 52ca123..7c8b593 100644 --- a/src/main/java/nl/iobyte/themepark/api/attraction/enums/Status.java +++ b/src/main/java/nl/iobyte/themepark/api/attraction/enums/Status.java @@ -7,6 +7,7 @@ import org.bukkit.inventory.ItemStack; public enum Status { + GLOBAL(0, "&1", "#3498db", "Global", "STAINED_CLAY:3", false), CONSTRUCTION(1, "&7", "#95a5a6", "Under Contruction", "STAINED_CLAY:1",false), OPEN(2, "&a", "#4cd137", "Open", "STAINED_CLAY:5", true), CLOSED(3, "&4", "#e84118", "Closed", "STAINED_CLAY:14", false), diff --git a/src/main/java/nl/iobyte/themepark/api/config/enums/StorageKey.java b/src/main/java/nl/iobyte/themepark/api/config/enums/StorageKey.java index 15ff545..3b214e8 100644 --- a/src/main/java/nl/iobyte/themepark/api/config/enums/StorageKey.java +++ b/src/main/java/nl/iobyte/themepark/api/config/enums/StorageKey.java @@ -2,6 +2,9 @@ package nl.iobyte.themepark.api.config.enums; public enum StorageKey { + //General Settings + CMD(StorageLocation.SETTINGS, "cmd"), + //Database Settings MYSQL_ENABLED(StorageLocation.SETTINGS, "mysql.enabled"), MYSQL_URL(StorageLocation.SETTINGS, "mysql.url"), @@ -12,7 +15,7 @@ public enum StorageKey { MYSQL_PASSWORD(StorageLocation.SETTINGS, "mysql.password"), //Menu Settings - MENU_ENABLED_MAIN(StorageLocation.MENU, "main.menu.enabled"), + MENU_ENABLED_MAIN(StorageLocation.MENU, "menu.main.enabled"), MENU_SIZE_MAIN(StorageLocation.MENU, "menu.main.size"), MENU_TITLE_MAIN(StorageLocation.MENU, "menu.main.title"), MENU_TITLE_STATUS(StorageLocation.MENU, "menu.status.title"), diff --git a/src/main/java/nl/iobyte/themepark/api/load/objects/StatusDataLoader.java b/src/main/java/nl/iobyte/themepark/api/load/objects/StatusDataLoader.java index 95cfc4c..9149fba 100644 --- a/src/main/java/nl/iobyte/themepark/api/load/objects/StatusDataLoader.java +++ b/src/main/java/nl/iobyte/themepark/api/load/objects/StatusDataLoader.java @@ -113,7 +113,7 @@ public class StatusDataLoader implements IDataLoader { return; ConfigurationSection section = config.getSection("attractions"); - if(section.getKeys(false).isEmpty()) + if(section == null || section.getKeys(false).isEmpty()) return; //Load Attractions diff --git a/src/main/java/nl/iobyte/themepark/commands/ThemeParkCommand.java b/src/main/java/nl/iobyte/themepark/commands/ThemeParkCommand.java index c794a79..814313c 100644 --- a/src/main/java/nl/iobyte/themepark/commands/ThemeParkCommand.java +++ b/src/main/java/nl/iobyte/themepark/commands/ThemeParkCommand.java @@ -4,6 +4,7 @@ import nl.iobyte.commandapi.CommandFactory; import nl.iobyte.commandapi.interfaces.ICommandExecutor; import nl.iobyte.commandapi.middlewares.PermissionMiddleware; import nl.iobyte.themepark.ThemePark; +import nl.iobyte.themepark.api.config.enums.StorageKey; import nl.iobyte.themepark.commands.executors.ConsoleExecutor; import nl.iobyte.themepark.commands.executors.PlayerExecutor; import nl.iobyte.themepark.commands.subcommands.HelpCommand; @@ -13,16 +14,21 @@ import nl.iobyte.themepark.commands.subcommands.attraction.AttractionCommands; import nl.iobyte.themepark.commands.subcommands.region.RegionCommands; import nl.iobyte.themepark.commands.subcommands.ridecount.RideCountCommands; import nl.iobyte.themepark.commands.subcommands.status.StatusCommands; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.lang.reflect.Field; public class ThemeParkCommand { //Load command data public ThemeParkCommand() { - CommandFactory factory = new CommandFactory("themepark"); + String cmd = ThemePark.getInstance().getAPI().getConfigurationManager().getString(StorageKey.CMD); + + CommandFactory factory = new CommandFactory(cmd); factory.addSubCommand(new HelpCommand(factory)) .addSubCommand(new MenuCommand()); @@ -45,14 +51,24 @@ public class ThemeParkCommand { factory.addMiddleware(new PermissionMiddleware()); //Register command - ThemePark.getInstance().getCommand(factory.getName()).setExecutor((sender, command, s, args) -> { - ICommandExecutor executor = new ConsoleExecutor(sender); - if(sender instanceof Player) - executor = new PlayerExecutor((Player) sender); + try { + Field bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + bukkitCommandMap.setAccessible(true); - factory.onCommand(executor, args); - return true; - }); + CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer()); + commandMap.register(cmd, new Command(cmd) { + public boolean execute(CommandSender sender, String label, String[] args) { + ICommandExecutor executor = new ConsoleExecutor(sender); + if(sender instanceof Player) + executor = new PlayerExecutor((Player) sender); + + factory.onCommand(executor, args); + return true; + } + }); + } catch(Exception e) { + e.printStackTrace(); + } } } diff --git a/src/main/java/nl/iobyte/themepark/listeners/PlayerListener.java b/src/main/java/nl/iobyte/themepark/listeners/PlayerListener.java index 941b137..ae5a562 100644 --- a/src/main/java/nl/iobyte/themepark/listeners/PlayerListener.java +++ b/src/main/java/nl/iobyte/themepark/listeners/PlayerListener.java @@ -132,6 +132,9 @@ public class PlayerListener implements Listener { return; Inventory inventory = e.getClickedInventory(); + if(inventory == null) + return; + if(inventory.getType() != InventoryType.PLAYER) return; diff --git a/src/main/java/nl/iobyte/themepark/utils/UpdateManager.java b/src/main/java/nl/iobyte/themepark/utils/UpdateManager.java new file mode 100644 index 0000000..b334315 --- /dev/null +++ b/src/main/java/nl/iobyte/themepark/utils/UpdateManager.java @@ -0,0 +1,312 @@ +package nl.iobyte.themepark.utils; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.net.ssl.HttpsURLConnection; +import java.io.*; +import java.lang.reflect.Method; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.charset.StandardCharsets; +import java.util.function.BiConsumer; + +/** + * Update class for SBDevelopment + * @author Stijn [SBDeveloper] + * @since 05-03-2020 + * @version 2.0 [26-12-2020] - This class supports the v2 Update API + * + *

© Stijn Bannink [stijnbannink23@gmail.com] - All rights reserved.

+ */ +public class UpdateManager { + + private static final String SPIGOT_API = "https://api.spigotmc.org/legacy/update.php?resource=%d"; + private static final String SPIGOT_DOWNLOAD = "http://api.spiget.org/v2/resources/%s/download"; + + private static final String SBDPLUGINS_API = "https://updates.sbdplugins.nl/api/v2/plugins/%d"; + private static final String SBDPLUGINS_DOWNLOAD = "https://updates.sbdplugins.nl/api/v2/download/%d"; + + private final Plugin plugin; + private final Version currentVersion; + private final int resourceID; + private final CheckType type; + private final String license; + + private BiConsumer versionResponse; + private BiConsumer downloadResponse; + + /** + * Construct a new UpdateManager for Spigot + * + * @param plugin The javaplugin (Main class) + * @param resourceID The resourceID on spigot/sbdplugins + */ + public UpdateManager(@NotNull Plugin plugin, int resourceID) { + this.plugin = plugin; + this.currentVersion = new Version(plugin.getDescription().getVersion()); + this.resourceID = resourceID; + this.type = CheckType.SPIGOT; + this.license = null; + } + + /** + * Construct a new UpdateManager for SBDPlugins + * + * @param plugin The javaplugin (Main class) + * @param resourceID The resourceID on spigot/sbdplugins + * @param license The license for the download + */ + public UpdateManager(@NotNull Plugin plugin, int resourceID, String license) { + this.plugin = plugin; + this.currentVersion = new Version(plugin.getDescription().getVersion()); + this.resourceID = resourceID; + this.type = CheckType.SBDPLUGINS; + this.license = license; + } + + /** + * Handle the response given by check(); + * @param versionResponse The response + * @return The updatemanager + */ + public UpdateManager handleResponse(BiConsumer versionResponse) { + this.versionResponse = versionResponse; + return this; + } + + public UpdateManager handleDownloadResponse(BiConsumer downloadResponse) { + this.downloadResponse = downloadResponse; + return this; + } + + /** + * Check for a new version + */ + public void check() { + Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> { + try { + BufferedReader in = null; + if (type == CheckType.SPIGOT) { + HttpsURLConnection con = (HttpsURLConnection) new URL(String.format(SPIGOT_API, this.resourceID)).openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("User-Agent", "Mozilla/5.0"); + + in = new BufferedReader(new InputStreamReader(con.getInputStream())); + } else if (type == CheckType.SBDPLUGINS) { + HttpsURLConnection con = (HttpsURLConnection) new URL(String.format(SBDPLUGINS_API, this.resourceID)).openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("User-Agent", "Mozilla/5.0"); + + in = new BufferedReader(new InputStreamReader(con.getInputStream())); + } + + if (in == null) return; + + String version; + + String inputLine; + StringBuilder response = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + + JsonParser parser = new JsonParser(); + + if (type == CheckType.SPIGOT) { + JsonArray array = parser.parse(response.toString()).getAsJsonArray(); + + version = array.get(0).getAsJsonObject().get("name").getAsString(); + } else { + JsonObject object = parser.parse(response.toString()).getAsJsonObject(); + + version = object.get("version").getAsString(); + } + + if (version == null) return; + + Version onlineVersion = new Version(version); + + VersionResponse verRes = this.currentVersion.check(onlineVersion); + + Bukkit.getScheduler().runTask(this.plugin, () -> this.versionResponse.accept(verRes, onlineVersion)); + } catch (IOException | NullPointerException e) { + e.printStackTrace(); + Bukkit.getScheduler().runTask(this.plugin, () -> this.versionResponse.accept(VersionResponse.UNAVAILABLE, null)); + } + }); + } + + public void runUpdate() { + File pluginFile = getPluginFile(); // /plugins/XXX.jar + if (pluginFile == null) { + this.downloadResponse.accept(DownloadResponse.ERROR, null); + Bukkit.getLogger().info("Pluginfile is null"); + return; + } + File updateFolder = Bukkit.getUpdateFolderFile(); + if (!updateFolder.exists()) { + if (!updateFolder.mkdirs()) { + this.downloadResponse.accept(DownloadResponse.ERROR, null); + Bukkit.getLogger().info("Updatefolder doesn't exists, and can't be made"); + return; + } + } + final File updateFile = new File(updateFolder, pluginFile.getName()); + + Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> { + ReadableByteChannel channel; + try { + //https://stackoverflow.com/questions/921262/how-to-download-and-save-a-file-from-internet-using-java + int response; + InputStream stream; + if (type == CheckType.SBDPLUGINS) { + HttpURLConnection connection = (HttpURLConnection) new URL(String.format(SBDPLUGINS_DOWNLOAD, this.resourceID)).openConnection(); + + String urlParameters = "license=" + license + "&port=" + Bukkit.getPort(); + byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8); + int postDataLength = postData.length; + + connection.setRequestMethod("GET"); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.setRequestProperty("charset", "utf-8"); + connection.setRequestProperty("Content-Length", Integer.toString(postDataLength)); + connection.setRequestProperty("User-Agent", "Mozilla/5.0"); + connection.setDoOutput(true); + + DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); + wr.write(postData); + wr.close(); + + response = connection.getResponseCode(); + stream = connection.getInputStream(); + } else { + HttpsURLConnection connection = (HttpsURLConnection) new URL(String.format(SPIGOT_DOWNLOAD, this.resourceID)).openConnection(); + connection.setRequestProperty("User-Agent", "Mozilla/5.0"); + + response = connection.getResponseCode(); + stream = connection.getInputStream(); + } + + if (response != 200) { + BufferedReader in = new BufferedReader(new InputStreamReader(stream)); + + String inputLine; + StringBuilder responsestr = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + responsestr.append(inputLine); + } + in.close(); + + throw new RuntimeException("Download returned status #" + response, new Throwable(responsestr.toString())); + } + + channel = Channels.newChannel(stream); + } catch (IOException e) { + Bukkit.getScheduler().runTask(this.plugin, () -> this.downloadResponse.accept(DownloadResponse.ERROR, null)); + e.printStackTrace(); + return; + } + + FileChannel fileChannel = null; + try { + FileOutputStream fosForDownloadedFile = new FileOutputStream(updateFile); + fileChannel = fosForDownloadedFile.getChannel(); + + fileChannel.transferFrom(channel, 0, Long.MAX_VALUE); + } catch (IOException e) { + Bukkit.getScheduler().runTask(this.plugin, () -> this.downloadResponse.accept(DownloadResponse.ERROR, null)); + e.printStackTrace(); + return; + } finally { + if (channel != null) { + try { + channel.close(); + } catch (IOException ioe) { + System.out.println("Error while closing response body channel"); + } + } + + if (fileChannel != null) { + try { + fileChannel.close(); + } catch (IOException ioe) { + System.out.println("Error while closing file channel for downloaded file"); + } + } + } + + Bukkit.getScheduler().runTask(this.plugin, () -> this.downloadResponse.accept(DownloadResponse.DONE, updateFile.getPath())); + }); + } + + @Nullable + private File getPluginFile() { + if (!(this.plugin instanceof JavaPlugin)) { return null; } + try { + Method method = JavaPlugin.class.getDeclaredMethod("getFile"); + method.setAccessible(true); + return (File) method.invoke(this.plugin); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Could not get plugin file", e); + } + } + + private enum CheckType { + SPIGOT, SBDPLUGINS + } + + public enum VersionResponse { + LATEST, //Latest version + FOUND_NEW, //Newer available + THIS_NEWER, //Local version is newer? + UNAVAILABLE //Error + } + + public enum DownloadResponse { + DONE, ERROR, UNAVAILABLE + } + + public static class Version { + + private final String version; + + public final String get() { + return this.version; + } + + private Version(String version) { + if(version == null) + throw new IllegalArgumentException("Version can not be null"); + if(!version.matches("[0-9]+(\\.[0-9]+)*")) + throw new IllegalArgumentException("Invalid version format"); + this.version = version; + } + + private VersionResponse check(@NotNull Version that) { + String[] thisParts = this.get().split("\\."); + String[] thatParts = that.get().split("\\."); + + int length = Math.max(thisParts.length, thatParts.length); + for (int i = 0; i < length; i++) { + int thisPart = i < thisParts.length ? Integer.parseInt(thisParts[i]) : 0; + int thatPart = i < thatParts.length ? Integer.parseInt(thatParts[i]) : 0; + if(thisPart < thatPart) + return VersionResponse.FOUND_NEW; + if(thisPart > thatPart) + return VersionResponse.THIS_NEWER; + } + return VersionResponse.LATEST; + } + } +} diff --git a/src/main/resources/menu.yml b/src/main/resources/menu.yml index 46a1769..a57f51a 100644 --- a/src/main/resources/menu.yml +++ b/src/main/resources/menu.yml @@ -1,4 +1,4 @@ -version: 1.0 +version: 1.1 menu: item: diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6e7bc54..c34d141 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,10 +1,7 @@ name: ThemePark -version: 3.0.2 +version: 3.0.3 author: IOByte website: 'https://www.iobyte.nl' main: nl.iobyte.themepark.ThemePark softdepend: [PlaceholderAPI,Train_Carts,Multiverse-Core,MultiWorld] -api-version: 1.13 -commands: - themepark: - aliases: [tp] \ No newline at end of file +api-version: 1.13 \ No newline at end of file diff --git a/src/main/resources/settings.yml b/src/main/resources/settings.yml index 3fcbd6e..6935723 100644 --- a/src/main/resources/settings.yml +++ b/src/main/resources/settings.yml @@ -1,4 +1,6 @@ -version: 1.1 +version: 1.2 + +cmd: "themepark" mysql: enabled: false diff --git a/themepark.iml b/themepark.iml index 894ee5d..a251abc 100644 --- a/themepark.iml +++ b/themepark.iml @@ -21,12 +21,14 @@ - + - + + + @@ -60,7 +62,6 @@ - @@ -75,7 +76,7 @@ - +