diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 57229eb..0000000 --- a/TODO.md +++ /dev/null @@ -1,12 +0,0 @@ -# Todo -## Auto updater -Automatically use latest version -## StackableItems -Make it configurable whether ItemStacks > 64 items will stay unsorted, or sorted and reverted back to stacks of 64 items --> https://www.spigotmc.org/threads/1-8-1-15-chestsort-api.334121/page-19#post-3821591 - -## Auto-Refill -Auto refills your hotbar with stuff from your inventory when you run out of items / a tool breaks. - -## MySQL -Optional MySQL support for player configs to avoid thousands of yaml files within the playerdata folder \ No newline at end of file diff --git a/pom.xml b/pom.xml index fc6bee5..703120d 100644 --- a/pom.xml +++ b/pom.xml @@ -9,12 +9,12 @@ ChestSort https://www.chestsort.de Allows automatic chest sorting! - 14.2.0 + 14.3.0 jar UTF-8 - 1.8 + 21 ${project.name} ${project.groupId}.chestsort.ChestSortPlugin @@ -45,53 +45,26 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.11.0 - ${java.version} - ${java.version} + ${java.version} org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.6.0 true - - com.jeff_media.jefflib - de.jeff_media.chestsort.jefflib - - - - org.apache.maven.artifact - de.jeff_media.chestsort.jefflib.thirdparty.org.apache.maven.artifact - - - - - com.jeff_media.updatechecker - de.jeff_media.chestsort.updatechecker - - org.bstats de.jeff_media.chestsort.bstats - - io.papermc.lib - de.jeff_media.chestsort.paperlib - - - - com.jeff_media.morepersistentdatatypes - com.jeff_media.chestsort.morepersistentdatatypes - - @@ -108,19 +81,6 @@ META-INF/** - - *:* - false - - de/jeff_media/jefflib/internal/nms/** - - - - *:* - - de/jeff_media/chestsortapi/** - - @@ -146,11 +106,6 @@ - - jeff-media-gbr - https://repo.jeff-media.com/public/ - - spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ @@ -158,7 +113,7 @@ papermc - https://papermc.io/repo/repository/maven-public/ + https://repo.papermc.io/repository/maven-public/ @@ -176,16 +131,6 @@ https://repo.codemc.org/repository/maven-public - - jeff-media-public - https://hub.jeff-media.com/nexus/repository/jeff-media-public/ - - - - pcgf-repo - https://repo.pcgamingfreaks.at/repository/maven-everything - - jitpack.io https://jitpack.io @@ -196,9 +141,9 @@ - org.spigotmc - spigot-api - 1.16.1-R0.1-SNAPSHOT + io.papermc.paper + paper-api + 1.21.4-R0.1-SNAPSHOT provided @@ -209,41 +154,6 @@ provided - - com.jeff_media - SpigotUpdateChecker - 2.2.0 - compile - - - - com.jeff_media - MorePersistentDataTypes - 2.3.1 - compile - - - - com.jeff-media.cesspool.modules - yaml-commands - 1.0-SNAPSHOT - compile - - - - com.jeff-media.jefflib - jefflib - 14.2.3 - compile - - - - de.jeff_media - InvUnload - 4.17.1 - provided - - me.clip placeholderapi @@ -265,19 +175,6 @@ compile - - at.pcgamingfreaks - Minepacks-API - 2.3.24 - provided - - - org.jetbrains - annotations - - - - com.github.Slimefun Slimefun4 @@ -285,13 +182,6 @@ provided - - io.papermc - paperlib - 1.0.8 - compile - - com.github.DeadSilenceIV AdvancedChestsAPI diff --git a/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java b/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java index 30d4c70..9091fcb 100644 --- a/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java +++ b/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java @@ -27,8 +27,6 @@ package de.jeff_media.chestsort; -import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksPlugin; -import com.jeff_media.updatechecker.UpdateChecker; import de.jeff_media.chestsort.commands.ChestSortCommand; import de.jeff_media.chestsort.commands.InvSortCommand; import de.jeff_media.chestsort.commands.TabCompleter; @@ -51,11 +49,8 @@ import de.jeff_media.chestsort.listeners.ChestSortListener; import de.jeff_media.chestsort.placeholders.Placeholders; import de.jeff_media.chestsort.utils.Utils; -import com.jeff_media.jefflib.JeffLib; -import com.jeff_media.jefflib.data.McVersion; -import com.jeff_media.jefflib.NBTAPI; -import io.papermc.lib.PaperLib; import org.bstats.bukkit.Metrics; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -96,7 +91,6 @@ public class ChestSortPlugin extends JavaPlugin { private ChestSortPermissionsHandler permissionsHandler; private SettingsGUI settingsGUI; private String sortingMethod; - private UpdateChecker updateChecker; private boolean usingMatchingConfig = true; private boolean verbose = true; private YamlConfiguration guiConfig = new YamlConfiguration(); @@ -323,14 +317,6 @@ public void setSortingMethod(String sortingMethod) { this.sortingMethod = sortingMethod; } - public UpdateChecker getUpdateChecker() { - return updateChecker; - } - - public void setUpdateChecker(UpdateChecker updateChecker) { - this.updateChecker = updateChecker; - } - public boolean isDebug() { return debug; } @@ -424,9 +410,6 @@ public void load(boolean reload) { if (reload) { unregisterAllPlayers(); reloadConfig(); - if (getUpdateChecker() != null) { - getUpdateChecker().stop(); - } } createConfig(); @@ -446,7 +429,7 @@ public void load(boolean reload) { && Bukkit.getPluginManager().getPlugin("InventoryPages") != null); setHookMinepacks(getConfig().getBoolean("hook-minepacks") - && Bukkit.getPluginManager().getPlugin("Minepacks") instanceof MinepacksPlugin); + && Bukkit.getPluginManager().getPlugin("Minepacks") != null); setHookAdvancedChests(getConfig().getBoolean("hook-advancedchests") && Bukkit.getPluginManager().getPlugin("AdvancedChests") != null); @@ -472,23 +455,6 @@ public void load(boolean reload) { new Messages(); setOrganizer(new ChestSortOrganizer(this)); setSettingsGUI(new SettingsGUI(this)); - try { - if (Class.forName("net.md_5.bungee.api.chat.BaseComponent") != null) { - setUpdateChecker(UpdateChecker.init(this, "https://api.jeff-media.de/chestsort/chestsort-latest-version.txt") - .setChangelogLink("https://www.chestsort.de/changelog") - .setDonationLink("https://paypal.me/mfnalex") - .setDownloadLink("https://www.chestsort.de") - .suppressUpToDateMessage(true)); - } else { - getLogger().severe("You are using an unsupported server software! Consider switching to Spigot or Paper!"); - getLogger().severe("The Update Checker will NOT work when using CraftBukkit instead of Spigot/Paper!"); - PaperLib.suggestPaper(this); - } - } catch (ClassNotFoundException e) { - getLogger().severe("You are using an unsupported server software! Consider switching to Spigot or Paper!"); - getLogger().severe("The Update Checker will NOT work when using CraftBukkit instead of Spigot/Paper!"); - PaperLib.suggestPaper(this); - } setListener(new ChestSortListener(this)); setHotkeyCooldown(new HashMap<>()); setPermissionsHandler(new ChestSortPermissionsHandler(this)); @@ -538,20 +504,6 @@ public void load(boolean reload) { getLogger().info("Categories: " + getCategoryList()); } - // TODO: Fix update checker for folia - if (getUpdateChecker() != null) { - if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("true")) { - if(!usingFolia) getUpdateChecker().checkEveryXHours(getUpdateCheckInterval()).checkNow(); - } // When set to on-startup, we check right now (delay 0) - else if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("on-startup")) { - if(!usingFolia) getUpdateChecker().checkNow(); - } - } - - if (getConfig().getString("check-for-updates").equalsIgnoreCase("false")) { - getUpdateChecker().setNotifyOpsOnJoin(false); - } - registerMetrics(); if (getConfig().getBoolean("dump")) { @@ -583,8 +535,6 @@ public void onEnable() { instance = this; - JeffLib.init(this); - /*String tmpVersion = getServer().getClass().getPackage().getName(); setMcVersion(tmpVersion.substring(tmpVersion.lastIndexOf('.') + 1)); tmpVersion = getMcVersion().substring(getMcVersion().indexOf("_") + 1); @@ -709,7 +659,7 @@ public void registerPlayerIfNeeded(Player p) { boolean changed; boolean hasSeenMessage; - if (playerFile.exists() || !McVersion.current().isAtLeast(1,14,4)) { + if (playerFile.exists() || !true) { // If the player settings file does not exist for this player, set it to the // default value activeForThisPlayer = playerConfig.getBoolean("sortingEnabled"); @@ -725,7 +675,7 @@ public void registerPlayerIfNeeded(Player p) { changed = true; - if (McVersion.current().isAtLeast(1,14,4)) { + if (true) { if (playerFile.delete()) { this.getLogger().info("Converted old .yml playerdata file to NBT tags for player " + p.getName()); } else { @@ -738,16 +688,16 @@ public void registerPlayerIfNeeded(Player p) { String fingerprint = getFingerprint(); - activeForThisPlayer = Boolean.parseBoolean(NBTAPI.getNBT(p, "sortingEnabled" + fingerprint, String.valueOf(playerConfig.getBoolean("sortingEnabled")))); - invActiveForThisPlayer = Boolean.parseBoolean(NBTAPI.getNBT(p, "invSortingEnabled" + fingerprint, String.valueOf(playerConfig.getBoolean("invSortingEnabled", getConfig().getBoolean("inv-sorting-enabled-by-default"))))); - middleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "middleClick" + fingerprint, String.valueOf(playerConfig.getBoolean("middleClick")))); - shiftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftClick" + fingerprint, String.valueOf(playerConfig.getBoolean("shiftClick")))); - doubleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "doubleClick" + fingerprint, String.valueOf(playerConfig.getBoolean("doubleClick")))); - shiftRightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftRightClick" + fingerprint, String.valueOf(playerConfig.getBoolean("shiftRightClick")))); - leftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "leftClick" + fingerprint, String.valueOf(playerConfig.getBoolean("leftClick", getConfig().getBoolean("additional-hotkeys.left-click"))))); - rightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "rightClick" + fingerprint, String.valueOf(playerConfig.getBoolean("rightClick", getConfig().getBoolean("additional-hotkeys.right-click"))))); - leftClickFromOutside = Boolean.parseBoolean(NBTAPI.getNBT(p, "leftClickOutside" + fingerprint, String.valueOf(playerConfig.getBoolean("leftClickOutside", getConfig().getBoolean("left-click-to-sort-enabled-by-default"))))); - hasSeenMessage = Boolean.parseBoolean(NBTAPI.getNBT(p, "hasSeenMessage" + fingerprint, String.valueOf("false"))); + activeForThisPlayer = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "sortingEnabled" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("sortingEnabled")))); + invActiveForThisPlayer = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "invSortingEnabled" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("invSortingEnabled", getConfig().getBoolean("inv-sorting-enabled-by-default"))))); + middleClick = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "middleClick" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("middleClick")))); + shiftClick = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "shiftClick" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("shiftClick")))); + doubleClick = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "doubleClick" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("doubleClick")))); + shiftRightClick = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "shiftRightClick" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("shiftRightClick")))); + leftClick = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "leftClick" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("leftClick", getConfig().getBoolean("additional-hotkeys.left-click"))))); + rightClick = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "rightClick" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("rightClick", getConfig().getBoolean("additional-hotkeys.right-click"))))); + leftClickFromOutside = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "leftClickOutside" + fingerprint), PersistentDataType.STRING, String.valueOf(playerConfig.getBoolean("leftClickOutside", getConfig().getBoolean("left-click-to-sort-enabled-by-default"))))); + hasSeenMessage = Boolean.parseBoolean(p.getPersistentDataContainer().getOrDefault(new NamespacedKey(this, "hasSeenMessage" + fingerprint), PersistentDataType.STRING, "false")); //System.out.println("Loading playersetting from NBT"); if(getConfig().getBoolean("show-message-again-after-logout")) { //System.out.println("show-message-again-after-logout is true, sooo..."); @@ -762,8 +712,8 @@ public void registerPlayerIfNeeded(Player p) { // when "show-message-again-after-logout" is enabled, we don't care if the // player already saw the message if (!getConfig().getBoolean("show-message-again-after-logout")) { - if (McVersion.current().isAtLeast(1,14,4) && !playerFile.exists()) { - NBTAPI.getNBT(p, "hasSeenMessage", String.valueOf(false)); + if (!playerFile.exists()) { + newSettings.hasSeenMessage = false; } else { newSettings.hasSeenMessage = playerConfig.getBoolean("hasSeenMessage"); } @@ -936,7 +886,7 @@ public void unregisterPlayer(Player p) { if (getPerPlayerSettings().containsKey(uniqueId.toString())) { PlayerSetting setting = getPerPlayerSettings().get(p.getUniqueId().toString()); - if (McVersion.current().isAtLeast(1,14,4)) { + if (true) { for(NamespacedKey key : p.getPersistentDataContainer().getKeys()) { if(key.getKey().equals(new NamespacedKey(this,"test").getKey())) { @@ -946,16 +896,16 @@ public void unregisterPlayer(Player p) { String fingerprint = getFingerprint(); - NBTAPI.addNBT(p, "sortingEnabled" + fingerprint, String.valueOf(setting.sortingEnabled)); - NBTAPI.addNBT(p, "invSortingEnabled" + fingerprint, String.valueOf(setting.invSortingEnabled)); - NBTAPI.addNBT(p, "hasSeenMessage" + fingerprint, String.valueOf(setting.hasSeenMessage)); - NBTAPI.addNBT(p, "middleClick" + fingerprint, String.valueOf(setting.middleClick)); - NBTAPI.addNBT(p, "shiftClick" + fingerprint, String.valueOf(setting.shiftClick)); - NBTAPI.addNBT(p, "doubleClick" + fingerprint, String.valueOf(setting.doubleClick)); - NBTAPI.addNBT(p, "shiftRightClick" + fingerprint, String.valueOf(setting.shiftRightClick)); - NBTAPI.addNBT(p, "leftClick" + fingerprint, String.valueOf(setting.leftClick)); - NBTAPI.addNBT(p, "rightClick" + fingerprint, String.valueOf(setting.rightClick)); - NBTAPI.addNBT(p, "leftClickOutside" + fingerprint, String.valueOf(setting.leftClickOutside)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "sortingEnabled" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.sortingEnabled)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "invSortingEnabled" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.invSortingEnabled)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "hasSeenMessage" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.hasSeenMessage)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "middleClick" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.middleClick)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "shiftClick" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.shiftClick)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "doubleClick" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.doubleClick)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "shiftRightClick" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.shiftRightClick)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "leftClick" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.leftClick)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "rightClick" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.rightClick)); + p.getPersistentDataContainer().set(new NamespacedKey(this, "leftClickOutside" + fingerprint), PersistentDataType.STRING, String.valueOf(setting.leftClickOutside)); } else { File playerFile = new File(getDataFolder() + File.separator + "playerdata", p.getUniqueId() + ".yml"); diff --git a/src/main/java/de/jeff_media/chestsort/commands/AdminCommand.java b/src/main/java/de/jeff_media/chestsort/commands/AdminCommand.java index 17cd489..20030d8 100644 --- a/src/main/java/de/jeff_media/chestsort/commands/AdminCommand.java +++ b/src/main/java/de/jeff_media/chestsort/commands/AdminCommand.java @@ -1,8 +1,9 @@ package de.jeff_media.chestsort.commands; import de.jeff_media.chestsort.ChestSortPlugin; -import com.jeff_media.jefflib.NBTAPI; import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -73,7 +74,7 @@ private void reset(CommandSender sender, String[] args) { }; for(String nbtTag : tags) { - NBTAPI.removeNBT(player,nbtTag); + player.getPersistentDataContainer().remove(new NamespacedKey(plugin, nbtTag)); } sender.sendMessage("Reset hotkey settings for player "+player.getName()); diff --git a/src/main/java/de/jeff_media/chestsort/config/Messages.java b/src/main/java/de/jeff_media/chestsort/config/Messages.java index 4731ca0..4ddc49d 100644 --- a/src/main/java/de/jeff_media/chestsort/config/Messages.java +++ b/src/main/java/de/jeff_media/chestsort/config/Messages.java @@ -1,7 +1,7 @@ package de.jeff_media.chestsort.config; import de.jeff_media.chestsort.ChestSortPlugin; -import com.jeff_media.jefflib.TextUtils; +import de.jeff_media.chestsort.utils.Utils; import org.bukkit.ChatColor; public class Messages { @@ -27,60 +27,60 @@ public Messages() { ChestSortPlugin plugin = ChestSortPlugin.getInstance(); - MSG_CONTAINER_SORTED = TextUtils.format( plugin.getConfig() + MSG_CONTAINER_SORTED = Utils.formatText( plugin.getConfig() .getString("message-container-sorted","&aContainer sorted!")); - MSG_ACTIVATED = TextUtils.format( plugin.getConfig() + MSG_ACTIVATED = Utils.formatText( plugin.getConfig() .getString("message-sorting-enabled", "&7Automatic chest sorting has been &aenabled&7.&r")); - MSG_DEACTIVATED = TextUtils.format( plugin.getConfig() + MSG_DEACTIVATED = Utils.formatText( plugin.getConfig() .getString("message-sorting-disabled", "&7Automatic chest sorting has been &cdisabled&7.&r")); - MSG_INVACTIVATED = TextUtils.format( plugin.getConfig() + MSG_INVACTIVATED = Utils.formatText( plugin.getConfig() .getString("message-inv-sorting-enabled", "&7Automatic inventory sorting has been &aenabled&7.&r")); - MSG_INVDEACTIVATED = TextUtils.format( plugin.getConfig() + MSG_INVDEACTIVATED = Utils.formatText( plugin.getConfig() .getString("message-inv-sorting-disabled", "&7Automatic inventory sorting has been &cdisabled&7.&r")); - MSG_COMMANDMESSAGE = TextUtils.format( plugin.getConfig().getString( + MSG_COMMANDMESSAGE = Utils.formatText( plugin.getConfig().getString( "message-when-using-chest", "&7Hint: Type &6/chestsort&7 to enable automatic chest sorting.")); - MSG_COMMANDMESSAGE2 = TextUtils.format( plugin.getConfig().getString( + MSG_COMMANDMESSAGE2 = Utils.formatText( plugin.getConfig().getString( "message-when-using-chest2", "&7Hint: Type &6/chestsort&7 to disable automatic chest sorting.")); - MSG_PLAYERSONLY = TextUtils.format( plugin.getConfig() + MSG_PLAYERSONLY = Utils.formatText( plugin.getConfig() .getString("message-error-players-only", "&cError: This command can only be run by players.&r")); - MSG_PLAYERINVSORTED = TextUtils.format( + MSG_PLAYERINVSORTED = Utils.formatText( plugin.getConfig().getString("message-player-inventory-sorted", "&7Your inventory has been sorted.")); - MSG_INVALIDOPTIONS = TextUtils.format( plugin.getConfig() + MSG_INVALIDOPTIONS = Utils.formatText( plugin.getConfig() .getString("message-error-invalid-options", "&cError: Unknown option %s. Valid options are %s.")); - MSG_GUI_ENABLED = TextUtils.format( plugin.getConfig() + MSG_GUI_ENABLED = Utils.formatText( plugin.getConfig() .getString("message-gui-enabled","&aEnabled")); - MSG_GUI_DISABLED = TextUtils.format( plugin.getConfig() + MSG_GUI_DISABLED = Utils.formatText( plugin.getConfig() .getString("message-gui-disabled","&cDisabled")); - MSG_GUI_MIDDLECLICK = TextUtils.format( plugin.getConfig() + MSG_GUI_MIDDLECLICK = Utils.formatText( plugin.getConfig() .getString("message-gui-middle-click","Middle-Click")); - MSG_GUI_SHIFTCLICK = TextUtils.format( plugin.getConfig() + MSG_GUI_SHIFTCLICK = Utils.formatText( plugin.getConfig() .getString("message-gui-shift-click","Shift + Click")); - MSG_GUI_DOUBLECLICK = TextUtils.format( plugin.getConfig() + MSG_GUI_DOUBLECLICK = Utils.formatText( plugin.getConfig() .getString("message-gui-double-click","Double-Click")); - MSG_GUI_LEFTCLICKOUTSIDE = TextUtils.format( plugin.getConfig() + MSG_GUI_LEFTCLICKOUTSIDE = Utils.formatText( plugin.getConfig() .getString("message-gui-left-click-outside", "Left-Click")); - MSG_GUI_SHIFTRIGHTCLICK = TextUtils.format( plugin.getConfig() + MSG_GUI_SHIFTRIGHTCLICK = Utils.formatText( plugin.getConfig() .getString("message-gui-shift-right-click","Shift + Right-Click")); - MSG_GUI_LEFTCLICK = TextUtils.format( plugin.getConfig().getString("message-gui-left-click","Fill Chest (Left-Click/Double-Left-Click)")); + MSG_GUI_LEFTCLICK = Utils.formatText( plugin.getConfig().getString("message-gui-left-click","Fill Chest (Left-Click/Double-Left-Click)")); - MSG_GUI_RIGHTCLICK = TextUtils.format( plugin.getConfig().getString("message-gui-right-click","Unload Chest (Right-Click/Double-Right-Click)")); + MSG_GUI_RIGHTCLICK = Utils.formatText( plugin.getConfig().getString("message-gui-right-click","Unload Chest (Right-Click/Double-Right-Click)")); MSG_ERR_HOTKEYSDISABLED = ChatColor.RED + "[ChestSort] Hotkeys have been disabled by the admin."; } diff --git a/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java b/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java index 7c748d7..7756be7 100644 --- a/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java +++ b/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java @@ -1,6 +1,5 @@ package de.jeff_media.chestsort.gui; -import com.jeff_media.morepersistentdatatypes.DataType; import de.jeff_media.chestsort.ChestSortPlugin; import de.jeff_media.chestsort.data.PlayerSetting; import de.jeff_media.chestsort.gui.tracker.CustomGUITracker; @@ -38,8 +37,8 @@ public void onClick(InventoryClickEvent event) { Player player = (Player) event.getWhoClicked(); PlayerSetting setting = main.getPlayerSetting(player); String function = Objects.requireNonNull(clicked.getItemMeta()).getPersistentDataContainer().getOrDefault(new NamespacedKey(main,"function"), PersistentDataType.STRING,""); - List userCommands = clicked.getItemMeta().getPersistentDataContainer().getOrDefault(new NamespacedKey(main,"user-commands"), DataType.asList(DataType.STRING), new ArrayList<>()); - List adminCommands = clicked.getItemMeta().getPersistentDataContainer().getOrDefault(new NamespacedKey(main,"admin-commands"), DataType.asList(DataType.STRING), new ArrayList<>()); + List userCommands = clicked.getItemMeta().getPersistentDataContainer().getOrDefault(new NamespacedKey(main,"user-commands"), PersistentDataType.LIST.strings(), new ArrayList<>()); + List adminCommands = clicked.getItemMeta().getPersistentDataContainer().getOrDefault(new NamespacedKey(main,"admin-commands"), PersistentDataType.LIST.strings(), new ArrayList<>()); executeCommands(player, player, userCommands); executeCommands(player, Bukkit.getConsoleSender(), adminCommands); diff --git a/src/main/java/de/jeff_media/chestsort/gui/NewUI.java b/src/main/java/de/jeff_media/chestsort/gui/NewUI.java index 79b851f..701c97c 100644 --- a/src/main/java/de/jeff_media/chestsort/gui/NewUI.java +++ b/src/main/java/de/jeff_media/chestsort/gui/NewUI.java @@ -1,22 +1,33 @@ package de.jeff_media.chestsort.gui; -import com.jeff_media.morepersistentdatatypes.DataType; +import com.google.gson.JsonParser; import de.jeff_media.chestsort.ChestSortPlugin; import de.jeff_media.chestsort.enums.Hotkey; -import com.jeff_media.jefflib.ItemStackUtils; -import com.jeff_media.jefflib.TextUtils; import de.jeff_media.chestsort.gui.tracker.CustomGUITracker; import de.jeff_media.chestsort.gui.tracker.CustomGUIType; +import de.jeff_media.chestsort.utils.Utils; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.persistence.PersistentDataType; +import org.bukkit.profile.PlayerProfile; +import org.bukkit.profile.PlayerTextures; +import java.net.URL; +import java.util.ArrayList; +import java.util.Base64; import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; public class NewUI { @@ -30,31 +41,28 @@ public NewUI(Player player) { private ItemStack getItem(int slot) { if(conf.isConfigurationSection("slots." + slot)) { - return ItemStackUtils.fromConfigurationSection(conf.getConfigurationSection("slots." + slot)); + return fromConfigurationSection(conf.getConfigurationSection("slots." + slot)); } if(conf.isString("slots." + slot)) { String buttonName = conf.getString("slots." + slot); - //if(!player.hasPermission("chestsort.hotkey." + buttonName)) { Hotkey key = Hotkey.fromPermission(buttonName); if(key != null && !Hotkey.fromPermission(buttonName).hasPermission(player)) { buttonName = buttonName + "-nopermission"; } else { boolean enabled = true; if(key != null) enabled = Hotkey.fromPermission(buttonName).hasEnabled(player); - //System.out.println(buttonName + " is enabled: " + enabled); if(key != null) buttonName = buttonName + (enabled ? "-enabled" : "-disabled"); } if(main.isDebug()) System.out.println("Button name: " + buttonName); - ItemStack button = ItemStackUtils.fromConfigurationSection(conf.getConfigurationSection("items." + buttonName)); - //System.out.println(button); + ItemStack button = fromConfigurationSection(conf.getConfigurationSection("items." + buttonName)); if(button.hasItemMeta() && !buttonName.endsWith("-nopermission")) { ItemMeta meta = button.getItemMeta(); assert meta != null; meta.getPersistentDataContainer().set(new NamespacedKey(main,"function"),PersistentDataType.STRING, buttonName.split("-")[0]); List userCommands = conf.getStringList("items." + buttonName + ".commands.player"); List adminCommands = conf.getStringList("items." + buttonName + ".commands.console"); - meta.getPersistentDataContainer().set(new NamespacedKey(main,"user-commands"), DataType.asList(DataType.STRING), userCommands); - meta.getPersistentDataContainer().set(new NamespacedKey(main,"admin-commands"), DataType.asList(DataType.STRING), adminCommands); + meta.getPersistentDataContainer().set(new NamespacedKey(main,"user-commands"), PersistentDataType.LIST.strings(), userCommands); + meta.getPersistentDataContainer().set(new NamespacedKey(main,"admin-commands"), PersistentDataType.LIST.strings(), adminCommands); button.setItemMeta(meta); } return button; @@ -64,10 +72,8 @@ private ItemStack getItem(int slot) { public void showGUI() { - NewUI gui = new NewUI(player); - int size = conf.getInt("size"); - String title = TextUtils.format(conf.getString("title")); + String title = Utils.formatText(conf.getString("title")); Inventory inv = Bukkit.createInventory(null, size, title); @@ -79,4 +85,75 @@ public void showGUI() { CustomGUITracker.open(player, inv, CustomGUIType.NEW); } + private static ItemStack fromConfigurationSection(ConfigurationSection section) { + if (section == null) return new ItemStack(Material.STONE); + + Material material; + try { + material = Material.valueOf(section.getString("material", "STONE").toUpperCase()); + } catch (IllegalArgumentException e) { + material = Material.STONE; + } + + int amount = section.getInt("amount", 1); + ItemStack item = new ItemStack(material, amount); + + // Apply base64 skull texture before touching ItemMeta for the first time + String base64 = section.getString("base64"); + if (base64 != null && material == Material.PLAYER_HEAD) { + try { + String decoded = new String(Base64.getDecoder().decode(base64)); + String url = JsonParser.parseString(decoded) + .getAsJsonObject() + .getAsJsonObject("textures") + .getAsJsonObject("SKIN") + .get("url").getAsString(); + SkullMeta skullMeta = (SkullMeta) item.getItemMeta(); + PlayerProfile profile = Bukkit.createPlayerProfile(UUID.randomUUID()); + PlayerTextures textures = profile.getTextures(); + textures.setSkin(new URL(url)); + profile.setTextures(textures); + skullMeta.setOwnerProfile(profile); + item.setItemMeta(skullMeta); + } catch (Exception ignored) { + // Invalid base64 or malformed texture JSON — leave as plain head + } + } + + ItemMeta meta = item.getItemMeta(); + if (meta == null) return item; + + String displayName = section.getString("display-name"); + if (displayName != null) { + meta.setDisplayName(Utils.formatText(displayName)); + } + + List loreStrings = section.getStringList("lore"); + if (!loreStrings.isEmpty()) { + meta.setLore(loreStrings.stream() + .map(Utils::formatText) + .collect(Collectors.toList())); + } + + if (section.isInt("custom-model-data")) { + meta.setCustomModelData(section.getInt("custom-model-data")); + } + + if (meta instanceof Damageable && section.isInt("damage")) { + ((Damageable) meta).setDamage(section.getInt("damage")); + } + + ConfigurationSection enchantSection = section.getConfigurationSection("enchantments"); + if (enchantSection != null) { + for (String key : enchantSection.getKeys(false)) { + Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(key.toLowerCase())); + if (enchantment != null) { + meta.addEnchant(enchantment, enchantSection.getInt(key), true); + } + } + } + + item.setItemMeta(meta); + return item; + } } diff --git a/src/main/java/de/jeff_media/chestsort/handlers/ChestSortOrganizer.java b/src/main/java/de/jeff_media/chestsort/handlers/ChestSortOrganizer.java index b6e3249..5387605 100644 --- a/src/main/java/de/jeff_media/chestsort/handlers/ChestSortOrganizer.java +++ b/src/main/java/de/jeff_media/chestsort/handlers/ChestSortOrganizer.java @@ -397,19 +397,22 @@ public Map getSortableMap(ItemStack item) { ItemMeta meta = item.getItemMeta(); if (meta instanceof PotionMeta) { PotionMeta potionMeta = (PotionMeta) meta; - // Only continue if Method "getBasePotionData" exists - Class potionMetaClass = potionMeta.getClass(); + // Try the new 1.20.5+ API (getBasePotionType) first, fall back to the old one try { - if (potionMeta.getBasePotionData() != null) { + org.bukkit.potion.PotionType potionType = potionMeta.getBasePotionType(); + if (potionType != null && potionType.getPotionEffects() != null && !potionType.getPotionEffects().isEmpty()) { + potionEffect = "|" + potionType.getPotionEffects().get(0).getType().getName(); + } + } catch (Throwable ignored) { + // Fall back to pre-1.20.5 API + try { PotionData pdata = potionMeta.getBasePotionData(); if (pdata != null && pdata.getType() != null && pdata.getType().getEffectType() != null) { potionEffect = "|" + pdata.getType().getEffectType().getName(); } + } catch (Throwable ignored2) { } - } catch (Throwable ignored) { } - - // potionEffects = potionEffects.substring(0, potionEffects.length()-1); } } diff --git a/src/main/java/de/jeff_media/chestsort/hooks/MinepacksHook.java b/src/main/java/de/jeff_media/chestsort/hooks/MinepacksHook.java index 6e06881..819447d 100644 --- a/src/main/java/de/jeff_media/chestsort/hooks/MinepacksHook.java +++ b/src/main/java/de/jeff_media/chestsort/hooks/MinepacksHook.java @@ -1,63 +1,64 @@ package de.jeff_media.chestsort.hooks; +import de.jeff_media.chestsort.ChestSortPlugin; import org.bukkit.Bukkit; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; -import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; -import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksPlugin; -import de.jeff_media.chestsort.ChestSortPlugin; +import java.lang.reflect.Method; public class MinepacksHook { final ChestSortPlugin plugin; - MinepacksPlugin minepacks = null; - boolean skipReflection = false; + Plugin minepacks = null; + Method isBackpackItemMethod = null; + Class backpackClass = null; public MinepacksHook(ChestSortPlugin plugin) { this.plugin = plugin; Plugin bukkitPlugin = Bukkit.getPluginManager().getPlugin("Minepacks"); - if (plugin.isHookMinepacks() && bukkitPlugin instanceof MinepacksPlugin) { - minepacks = (MinepacksPlugin) bukkitPlugin; - plugin.getLogger().info("Successfully hooked into Minepacks"); + if (plugin.isHookMinepacks() && bukkitPlugin != null) { + try { + Class.forName("at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksPlugin"); + backpackClass = Class.forName("at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack"); + minepacks = bukkitPlugin; + try { + isBackpackItemMethod = minepacks.getClass().getMethod("isBackpackItem", ItemStack.class); + } catch (NoSuchMethodException e) { + plugin.getLogger().warning("Minepacks version too old; hook disabled."); + plugin.setHookMinepacks(false); + } + if (minepacks != null) { + plugin.getLogger().info("Successfully hooked into Minepacks"); + } + } catch (ClassNotFoundException e) { + plugin.getLogger().warning("Minepacks API classes not found; hook disabled."); + plugin.setHookMinepacks(false); + } } } public boolean isMinepacksBackpack(ItemStack item) { - if (minepacks == null) { + if (minepacks == null || isBackpackItemMethod == null) { return false; } - if (skipReflection && minepacks.isBackpackItem(item)) { - return true; - } - try { - minepacks.getClass().getMethod("isBackpackItem", ItemStack.class); - skipReflection = true; - if (minepacks.isBackpackItem(item)) { - return true; - } - } catch (NoSuchMethodException | SecurityException e) { - plugin.getLogger().warning( - "You are using a version of Minepacks that is too old and does not implement every API method needed by ChestSort. Minepacks hook will be disabled."); + return (boolean) isBackpackItemMethod.invoke(minepacks, item); + } catch (Exception e) { + plugin.getLogger().warning("Minepacks hook error; disabling."); minepacks = null; plugin.setHookMinepacks(false); + return false; } - - return false; } public boolean isMinepacksBackpack(Inventory inv, InventoryHolder holder) { - if (minepacks == null) { + if (minepacks == null || backpackClass == null || holder == null) { return false; } - if (holder == null) { - return false; - } - return holder instanceof Backpack; - + return backpackClass.isInstance(holder); } } diff --git a/src/main/java/de/jeff_media/chestsort/listeners/ChestSortListener.java b/src/main/java/de/jeff_media/chestsort/listeners/ChestSortListener.java index 9eba8f2..7f8de99 100644 --- a/src/main/java/de/jeff_media/chestsort/listeners/ChestSortListener.java +++ b/src/main/java/de/jeff_media/chestsort/listeners/ChestSortListener.java @@ -1,6 +1,5 @@ package de.jeff_media.chestsort.listeners; -import com.jeff_media.jefflib.ProtectionUtils; import de.jeff_media.chestsort.ChestSortPlugin; import de.jeff_media.chestsort.api.ChestSortEvent; import de.jeff_media.chestsort.api.ChestSortPostSortEvent; @@ -35,6 +34,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryOpenEvent; @@ -164,9 +164,9 @@ public void onLeftClickChest(PlayerInteractEvent event) { } if (plugin.getConfig().getBoolean("mute-protection-plugins")) { - if (!ProtectionUtils.canBreak(event.getPlayer(), - clickedBlock.getLocation()/*, plugin.getConfig().getBoolean("mute-protection-plugins")*/)) { - //System.out.println("ChestSort: cannot interact!"); + BlockBreakEvent breakTest = new BlockBreakEvent(clickedBlock, event.getPlayer()); + Bukkit.getPluginManager().callEvent(breakTest); + if (breakTest.isCancelled()) { return; } } @@ -372,6 +372,12 @@ public void onChestClose(InventoryCloseEvent event) { return; } + // For ender chests, sort the player's actual ender chest inventory directly + if (inventory.getType() == InventoryType.ENDER_CHEST) { + plugin.getOrganizer().sortInventory(p.getEnderChest()); + return; + } + // Normal container inventories can be sorted completely plugin.getOrganizer().sortInventory(inventory); } @@ -573,18 +579,19 @@ public void onEnderChestOpen(InventoryOpenEvent event) { return; } - // Check if this is an EnderChest (is there a smarter way?) - if (!inventory.equals(p.getEnderChest())) { + // Check if this is a vanilla EnderChest by inventory type + if (inventory.getType() != InventoryType.ENDER_CHEST) { return; } if (isReadyToSort(p)) { // Finally call the Organizer to sort the inventory + // Use p.getEnderChest() directly to ensure we sort the actual backing inventory plugin.getLgr().logSort(p, Logger.SortCause.EC_OPEN); - plugin.getOrganizer().sortInventory(inventory); + plugin.getOrganizer().sortInventory(p.getEnderChest()); } } @@ -638,10 +645,11 @@ public void onHotkey(InventoryClickEvent event) { } - // Possible fix for #57 + // Possible fix for #57 — but ender chests also have the player as holder, so exclude them if (!isAPICall && (holder != null && holder == p && - clicked != p.getInventory())) { + clicked != p.getInventory() && + clicked.getType() != InventoryType.ENDER_CHEST)) { return; } @@ -824,11 +832,11 @@ public void onAdditionalHotkeys(InventoryClickEvent event) { advancedChestsHook.isAnAdvancedChest(inventory); // Possible fix for #57 - if (holder == null && !view.getTopInventory().equals(player.getEnderChest()) && + if (holder == null && view.getTopInventory().getType() != InventoryType.ENDER_CHEST && !isAdvancedChest) { return; } - if (holder == player && inventory != player.getInventory()) { + if (holder == player && inventory != player.getInventory() && inventory.getType() != InventoryType.ENDER_CHEST) { return; } // End Possible fix for #57 @@ -840,7 +848,7 @@ public void onAdditionalHotkeys(InventoryClickEvent event) { !inventory.getType().name().equalsIgnoreCase("SHULKER_BOX") && (holder == null || !holder.getClass().toString().endsWith(".CraftBarrel")) && - inventory != player.getEnderChest() && !(holder instanceof ISortable)) { + inventory.getType() != InventoryType.ENDER_CHEST && !(holder instanceof ISortable)) { return; } diff --git a/src/main/java/de/jeff_media/chestsort/utils/Utils.java b/src/main/java/de/jeff_media/chestsort/utils/Utils.java index ba91fa0..ad09dc1 100644 --- a/src/main/java/de/jeff_media/chestsort/utils/Utils.java +++ b/src/main/java/de/jeff_media/chestsort/utils/Utils.java @@ -5,13 +5,41 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import de.jeff_media.chestsort.ChestSortPlugin; +import org.bukkit.ChatColor; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; public class Utils { + private static final Pattern HEX_PATTERN = Pattern.compile("<#([0-9a-fA-F]{6})>"); + + /** + * Converts a string with legacy & colour codes and <#rrggbb> hex colour + * tags into a Bukkit-formatted string (§ codes). + */ + public static String formatText(String text) { + if (text == null) return ""; + // Strip gradient-end tags like <#/85c1e9> + text = text.replaceAll("<#/[0-9a-fA-F]{6}>", ""); + // Convert <#rrggbb> to Spigot §x§r§r§g§g§b§b hex format + Matcher matcher = HEX_PATTERN.matcher(text); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String hex = matcher.group(1); + StringBuilder spigotHex = new StringBuilder("§x"); + for (char c : hex.toCharArray()) { + spigotHex.append('§').append(c); + } + matcher.appendReplacement(sb, Matcher.quoteReplacement(spigotHex.toString())); + } + matcher.appendTail(sb); + return ChatColor.translateAlternateColorCodes('&', sb.toString()); + } + public static ItemStack[] getStorageContents(Inventory inv) { return inv.getStorageContents(); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 9173527..4ffa21a 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,16 +1,16 @@ main: ${spigot.main} name: ${project.name} version: ${project.version} -api-version: "1.13" +api-version: "1.21" description: "${project.description}" folia-supported: true authors: - mfnalex - JEFF Media GbR + - SamsSide website: ${project.url} prefix: ${spigot.prefix} database: false -loadbefore: [InvUnload] softdepend: [CrackShot,InventoryPages,Minepacks,PlaceholderAPI,AdvancedChests,ShulkerPacks] commands: sort: