From c700ccbe7044fc2448dc096d34d3d43f778b9178 Mon Sep 17 00:00:00 2001 From: mfnalex <1122571+mfnalex@users.noreply.github.com> Date: Sat, 9 Oct 2021 19:46:07 +0200 Subject: [PATCH] 12.0.0 --- CHANGELOG.md | 13 +- pom.xml | 2 +- .../jeff_media/chestsort/ChestSortPlugin.java | 110 +++++-- .../chestsort/commands/ChestSortCommand.java | 43 ++- .../chestsort/commands/TabCompleter.java | 9 +- .../de/jeff_media/chestsort/enums/Hotkey.java | 70 +++++ .../chestsort/gui/ChestSortGUIHolder.java | 20 ++ .../jeff_media/chestsort/gui/GUIListener.java | 49 +++ .../de/jeff_media/chestsort/gui/NewUI.java | 73 +++++ .../chestsort/listeners/Listener.java | 9 +- src/main/resources/config.yml | 15 +- src/main/resources/gui.yml | 292 ++++++++++++++++++ src/main/resources/plugin.yml | 12 +- src/main/resources/settings.fingerprint | 1 + 14 files changed, 669 insertions(+), 49 deletions(-) create mode 100644 src/main/java/de/jeff_media/chestsort/gui/ChestSortGUIHolder.java create mode 100644 src/main/java/de/jeff_media/chestsort/gui/GUIListener.java create mode 100644 src/main/java/de/jeff_media/chestsort/gui/NewUI.java create mode 100644 src/main/resources/gui.yml create mode 100644 src/main/resources/settings.fingerprint diff --git a/CHANGELOG.md b/CHANGELOG.md index b9f6359..a569958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Changelog -## 1.5.5 +## 12.0.0 +- GUI is now 100% customizable! + - Supports Custom Model Data to create vanilla-looking GUIs + - Change names, items, slots, lore, and basically EVERYTHING + - Also supports changing automatic sorting and automatic inventory sorting +- You can now reset the settings for all players using /sort resetplayerdata + - This is useful when you had some hotkeys enabled by default and changed it now, without having all players individually change their settings + +## 11.5.6 +- Added option to disable "use-advanced-protection-plugin-detection" as it causes some troubles when other plugins blindly cast a Player object to CraftPlayer, without prior checking whether it's an instanceof CraftPlayer + +## 11.5.5 - Fixed furnaces being sortable using the left-click hotkey ## 11.5.4 diff --git a/pom.xml b/pom.xml index 490395a..d11b643 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ ChestSort https://www.chestsort.de Allows automatic chest sorting! - 11.5.5 + 12.0.0 jar diff --git a/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java b/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java index c36cc41..7367a1d 100644 --- a/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java +++ b/src/main/java/de/jeff_media/chestsort/ChestSortPlugin.java @@ -37,6 +37,8 @@ import de.jeff_media.chestsort.config.ConfigUpdater; import de.jeff_media.chestsort.config.Messages; import de.jeff_media.chestsort.data.Category; import de.jeff_media.chestsort.data.PlayerSetting; +import de.jeff_media.chestsort.gui.ChestSortGUIHolder; +import de.jeff_media.chestsort.gui.GUIListener; import de.jeff_media.chestsort.gui.SettingsGUI; import de.jeff_media.chestsort.handlers.ChestSortOrganizer; import de.jeff_media.chestsort.handlers.ChestSortPermissionsHandler; @@ -56,11 +58,13 @@ import io.papermc.lib.PaperLib; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; +import org.yaml.snakeyaml.Yaml; import java.io.*; import java.util.*; @@ -95,11 +99,15 @@ public class ChestSortPlugin extends JavaPlugin { private UpdateChecker updateChecker; private boolean usingMatchingConfig = true; private boolean verbose = true; + private YamlConfiguration guiConfig = new YamlConfiguration(); + private int settingsFingerprint = 0; public static ChestSortPlugin getInstance() { return instance; } + public YamlConfiguration getGuiConfig() { return guiConfig; } + public static double getUpdateCheckInterval() { return updateCheckInterval; } @@ -125,6 +133,7 @@ public class ChestSortPlugin extends JavaPlugin { // This saves the config.yml included in the .jar file, but it will not // overwrite an existing config.yml this.saveDefaultConfig(); + createGUIConfig(); reloadConfig(); // Load disabled-worlds. If it does not exist in the config, it returns null. @@ -139,6 +148,14 @@ public class ChestSortPlugin extends JavaPlugin { } + private void createGUIConfig() { + File guiFile = new File(getDataFolder(), "gui.yml"); + if(!guiFile.exists()) { + saveResource("gui.yml",false); + } + guiConfig = YamlConfiguration.loadConfiguration(guiFile); + } + private void createDirectories() { // Create a playerdata folder that contains all the perPlayerSettings as .yml File playerDataFolder = new File(getDataFolder().getPath() + File.separator + "playerdata"); @@ -411,6 +428,13 @@ public class ChestSortPlugin extends JavaPlugin { public void load(boolean reload) { + settingsFingerprint = 0; + File fingerprintFile = new File(getDataFolder(), "settings.fingerprint"); + if(fingerprintFile.exists()) { + YamlConfiguration yaml = YamlConfiguration.loadConfiguration(fingerprintFile); + settingsFingerprint = yaml.getInt("v",0); + } + if (reload) { unregisterAllPlayers(); reloadConfig(); @@ -477,6 +501,7 @@ public class ChestSortPlugin extends JavaPlugin { setEnderContainersHook(new EnderContainersHook(this)); getServer().getPluginManager().registerEvents(getListener(), this); getServer().getPluginManager().registerEvents(getSettingsGUI(), this); + getServer().getPluginManager().registerEvents(new GUIListener(), this); ChestSortCommand chestsortCommandExecutor = new ChestSortCommand(this); TabCompleter tabCompleter = new TabCompleter(); this.getCommand("sort").setExecutor(chestsortCommandExecutor); @@ -484,7 +509,7 @@ public class ChestSortPlugin extends JavaPlugin { InvSortCommand invsortCommandExecutor = new InvSortCommand(this); this.getCommand("invsort").setExecutor(invsortCommandExecutor); this.getCommand("invsort").setTabCompleter(tabCompleter); - this.getCommand("chestsortadmin").setExecutor(new AdminCommand(this)); + //this.getCommand("chestsortadmin").setExecutor(new AdminCommand(this)); if (isVerbose()) { getLogger().info("Use permissions: " + getConfig().getBoolean("use-permissions")); @@ -546,9 +571,12 @@ public class ChestSortPlugin extends JavaPlugin { @Override public void onDisable() { // We have to unregister every player to save their perPlayerSettings - for (Player p : getServer().getOnlinePlayers()) { - unregisterPlayer(p); - getPermissionsHandler().removePermissions(p); + for (Player player : getServer().getOnlinePlayers()) { + if(player.getOpenInventory().getTopInventory().getHolder() instanceof ChestSortGUIHolder) { + player.closeInventory(); + } + unregisterPlayer(player); + getPermissionsHandler().removePermissions(player); } } @@ -624,6 +652,18 @@ public class ChestSortPlugin extends JavaPlugin { } + public void incrementFingerprint() { + YamlConfiguration yaml = new YamlConfiguration(); + yaml.set("v",settingsFingerprint + 1); + settingsFingerprint++; + try { + yaml.save(new File(getDataFolder(),"settings.fingerprint")); + load(true); + } catch (IOException e) { + e.printStackTrace(); + } + } + public void registerPlayerIfNeeded(Player p) { // Players are stored by their UUID, so that name changes don't break player's // settings @@ -685,16 +725,19 @@ public class ChestSortPlugin extends JavaPlugin { } else { // If the file exists, check if the player has sorting enabled // NBT Values - activeForThisPlayer = Boolean.parseBoolean(NBTAPI.getNBT(p, "sortingEnabled", String.valueOf(playerConfig.getBoolean("sortingEnabled")))); - invActiveForThisPlayer = Boolean.parseBoolean(NBTAPI.getNBT(p, "invSortingEnabled", String.valueOf(playerConfig.getBoolean("invSortingEnabled", getConfig().getBoolean("inv-sorting-enabled-by-default"))))); - middleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "middleClick", String.valueOf(playerConfig.getBoolean("middleClick")))); - shiftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftClick", String.valueOf(playerConfig.getBoolean("shiftClick")))); - doubleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "doubleClick", String.valueOf(playerConfig.getBoolean("doubleClick")))); - shiftRightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftRightClick", String.valueOf(playerConfig.getBoolean("shiftRightClick")))); - leftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "leftClick", String.valueOf(playerConfig.getBoolean("leftClick", getConfig().getBoolean("additional-hotkeys.left-click"))))); - rightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "rightClick", String.valueOf(playerConfig.getBoolean("rightClick", getConfig().getBoolean("additional-hotkeys.right-click"))))); - leftClickFromOutside = Boolean.parseBoolean(NBTAPI.getNBT(p, "leftClickOutside", String.valueOf(playerConfig.getBoolean("leftClickOutside", getConfig().getBoolean("left-click-to-sort-enabled-by-default"))))); - hasSeenMessage = Boolean.parseBoolean(NBTAPI.getNBT(p, "hasSeenMessage", String.valueOf("false"))); + + 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"))); //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..."); @@ -722,6 +765,14 @@ public class ChestSortPlugin extends JavaPlugin { } } + private String getFingerprint() { + String fingerprint = ""; + if(settingsFingerprint > 0) { + fingerprint = "-" + settingsFingerprint; + } + return fingerprint; + } + // Saves default category files, when enabled in the config private void saveDefaultCategories() { @@ -837,6 +888,8 @@ public class ChestSortPlugin extends JavaPlugin { getConfig().addDefault("hook-generic", true); getConfig().addDefault("prevent-sorting-null-inventories", false); + getConfig().addDefault("mute-protection-plugins", false); + getConfig().addDefault("verbose", true); // Prints some information in onEnable() } @@ -874,16 +927,25 @@ public class ChestSortPlugin extends JavaPlugin { PlayerSetting setting = getPerPlayerSettings().get(p.getUniqueId().toString()); if (McVersion.isAtLeast(1,14,4)) { - NBTAPI.addNBT(p, "sortingEnabled", String.valueOf(setting.sortingEnabled)); - NBTAPI.addNBT(p, "invSortingEnabled", String.valueOf(setting.invSortingEnabled)); - NBTAPI.addNBT(p, "hasSeenMessage", String.valueOf(setting.hasSeenMessage)); - NBTAPI.addNBT(p, "middleClick", String.valueOf(setting.middleClick)); - NBTAPI.addNBT(p, "shiftClick", String.valueOf(setting.shiftClick)); - NBTAPI.addNBT(p, "doubleClick", String.valueOf(setting.doubleClick)); - NBTAPI.addNBT(p, "shiftRightClick", String.valueOf(setting.shiftRightClick)); - NBTAPI.addNBT(p, "leftClick", String.valueOf(setting.leftClick)); - NBTAPI.addNBT(p, "rightClick", String.valueOf(setting.rightClick)); - NBTAPI.addNBT(p, "leftClickOutside", String.valueOf(setting.leftClickOutside)); + + for(NamespacedKey key : p.getPersistentDataContainer().getKeys()) { + if(key.getKey().equals(new NamespacedKey(this,"test").getKey())) { + p.getPersistentDataContainer().remove(key); + } + } + + 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)); } else { File playerFile = new File(getDataFolder() + File.separator + "playerdata", p.getUniqueId() + ".yml"); diff --git a/src/main/java/de/jeff_media/chestsort/commands/ChestSortCommand.java b/src/main/java/de/jeff_media/chestsort/commands/ChestSortCommand.java index cef3fb1..a2b9647 100644 --- a/src/main/java/de/jeff_media/chestsort/commands/ChestSortCommand.java +++ b/src/main/java/de/jeff_media/chestsort/commands/ChestSortCommand.java @@ -3,8 +3,10 @@ package de.jeff_media.chestsort.commands; import de.jeff_media.chestsort.ChestSortPlugin; import de.jeff_media.chestsort.config.Messages; import de.jeff_media.chestsort.data.PlayerSetting; +import de.jeff_media.chestsort.gui.NewUI; import de.jeff_media.chestsort.handlers.Debugger; import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -40,6 +42,17 @@ public class ChestSortCommand implements CommandExecutor { return true; } + //System.out.println(1); + if(sender.hasPermission("chestsort.resetplayersettings") && args.length > 0 && args[0].equalsIgnoreCase("resetplayersettings")) { + for(Player online : Bukkit.getOnlinePlayers()) { + plugin.unregisterPlayer(online); + } + plugin.incrementFingerprint(); + sender.sendMessage("§cAll player settings have been reset!"); + return true; + } + //System.out.println(2); + // Reload command if (args.length > 0 && args[0].equalsIgnoreCase("reload")) { if (!sender.hasPermission("chestsort.reload")) { @@ -92,8 +105,13 @@ public class ChestSortCommand implements CommandExecutor { if(!p.hasPermission("chestsort.automatic")) args = new String[]{"hotkeys"}; + if(args.length > 0 && (args[0].equalsIgnoreCase("hotkeys") || args[0].equalsIgnoreCase("hotkey"))) { + new NewUI(p).showGUI(); + return true; + } + // Settings GUI - if (args.length > 0) { + /*if (args.length > 0) { if (args[0].equalsIgnoreCase("hotkey") || args[0].equalsIgnoreCase("hotkeys")) { if (!plugin.isHotkeyGUI()) { @@ -106,7 +124,7 @@ public class ChestSortCommand implements CommandExecutor { return true; } - } + }*/ // Settings GUI End PlayerSetting setting = plugin.getPerPlayerSettings().get(p.getUniqueId().toString()); @@ -115,20 +133,25 @@ public class ChestSortCommand implements CommandExecutor { p.sendMessage(String.format(Messages.MSG_INVALIDOPTIONS, "\"" + args[0] + "\"", "\"toggle\", \"on\", \"off\", \"hotkeys\"")); return true; } - if (args.length == 0 || args[0].equalsIgnoreCase("toggle")) { - setting.toggleChestSorting(); - } else if (args[0].equalsIgnoreCase("on")) { - setting.enableChestSorting(); - } else if (args[0].equalsIgnoreCase("off")) { - setting.disableChestSorting(); + + if(args.length > 0) { + if (args[0].equalsIgnoreCase("toggle")) { + setting.toggleChestSorting(); + } else if (args[0].equalsIgnoreCase("on")) { + setting.enableChestSorting(); + } else if (args[0].equalsIgnoreCase("off")) { + setting.disableChestSorting(); + } } setting.hasSeenMessage = true; - if (setting.sortingEnabled) { + /*if (setting.sortingEnabled) { p.sendMessage(Messages.MSG_ACTIVATED); } else { p.sendMessage(Messages.MSG_DEACTIVATED); - } + }*/ + + new NewUI(p).showGUI(); return true; } diff --git a/src/main/java/de/jeff_media/chestsort/commands/TabCompleter.java b/src/main/java/de/jeff_media/chestsort/commands/TabCompleter.java index 3923345..52bbc2b 100644 --- a/src/main/java/de/jeff_media/chestsort/commands/TabCompleter.java +++ b/src/main/java/de/jeff_media/chestsort/commands/TabCompleter.java @@ -37,7 +37,14 @@ public class TabCompleter implements org.bukkit.command.TabCompleter { entered = args[args.length-1]; } if(command.getName().equalsIgnoreCase("sort")) { - return getMatchingOptions(entered,chestsortOptions); + List list = getMatchingOptions(entered,chestsortOptions); + if(sender.hasPermission("chestsort.reload")) { + list.add("reload"); + } + if(sender.isOp()) { + list.add("resetplayersettings"); + } + return list; } if(command.getName().equalsIgnoreCase("invsort")) { return getMatchingOptions(entered,invsortOptions); diff --git a/src/main/java/de/jeff_media/chestsort/enums/Hotkey.java b/src/main/java/de/jeff_media/chestsort/enums/Hotkey.java index 68d7401..cabb3b9 100644 --- a/src/main/java/de/jeff_media/chestsort/enums/Hotkey.java +++ b/src/main/java/de/jeff_media/chestsort/enums/Hotkey.java @@ -1,16 +1,86 @@ package de.jeff_media.chestsort.enums; +import de.jeff_media.chestsort.ChestSortPlugin; +import de.jeff_media.chestsort.data.PlayerSetting; +import org.bukkit.entity.Player; + import java.util.Locale; public enum Hotkey { + AUTO_SORT, AUTO_INV_SORT, SHIFT_CLICK, MIDDLE_CLICK, DOUBLE_CLICK, SHIFT_RIGHT_CLICK, OUTSIDE, LEFT_CLICK, RIGHT_CLICK; + private static final ChestSortPlugin main = ChestSortPlugin.getInstance(); + + public boolean hasPermission(Player player) { + if(!player.hasPermission(getPermission(this))) return false; + switch(this) { + case AUTO_SORT: + return main.getConfig().getBoolean("allow-automatic-sorting"); + case AUTO_INV_SORT: + return main.getConfig().getBoolean("allow-automatic-inventory-sorting"); + case SHIFT_CLICK: + case MIDDLE_CLICK: + case DOUBLE_CLICK: + case SHIFT_RIGHT_CLICK: + return main.getConfig().getBoolean("allow-sorting-hotkeys"); + case LEFT_CLICK: + case RIGHT_CLICK: + return main.getConfig().getBoolean("allow-additional-hotkeys"); + case OUTSIDE: + return main.getConfig().getBoolean("allow-left-click-to-sort"); + default: + throw new IllegalArgumentException("Invalid hotkey: " + this.name()); + } + } + public static String getPermission(Hotkey hotkey) { + + if(hotkey == AUTO_SORT) { + return "chestsort.use"; + } + + if(hotkey == AUTO_INV_SORT) { + return "chestsort.use.inventory"; + } + String permission = "chestsort.hotkey." + hotkey.name().toLowerCase(Locale.ROOT).replace("_", ""); //System.out.println("Permission for " + hotkey.name()+ ": " + permission); return permission; } + + public static Hotkey fromPermission(String permission) { + //System.out.println("Checking permission " + permission + " and returning the proper hotkey..."); + switch(permission) { + case "shiftclick": return SHIFT_CLICK; + case "middleclick": return MIDDLE_CLICK; + case "doubleclick": return DOUBLE_CLICK; + case "shiftrightclick": return SHIFT_RIGHT_CLICK; + case "leftclick": return LEFT_CLICK; + case "rightclick": return RIGHT_CLICK; + case "outside": return OUTSIDE; + case "autosorting": return AUTO_SORT; + case "autoinvsorting": return AUTO_INV_SORT; + default: return null; + } + } + + public boolean hasEnabled(Player player) { + PlayerSetting setting = ChestSortPlugin.getInstance().getPlayerSetting(player); + switch(this) { + case SHIFT_CLICK: return setting.shiftClick; + case MIDDLE_CLICK: return setting.middleClick; + case DOUBLE_CLICK: return setting.doubleClick; + case SHIFT_RIGHT_CLICK: return setting.shiftRightClick; + case LEFT_CLICK: return setting.leftClick; + case RIGHT_CLICK: return setting.rightClick; + case OUTSIDE: return setting.leftClickOutside; + case AUTO_INV_SORT: return setting.invSortingEnabled; + case AUTO_SORT: return setting.sortingEnabled; + default: return false; + } + } } diff --git a/src/main/java/de/jeff_media/chestsort/gui/ChestSortGUIHolder.java b/src/main/java/de/jeff_media/chestsort/gui/ChestSortGUIHolder.java new file mode 100644 index 0000000..469c42a --- /dev/null +++ b/src/main/java/de/jeff_media/chestsort/gui/ChestSortGUIHolder.java @@ -0,0 +1,20 @@ +package de.jeff_media.chestsort.gui; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.jetbrains.annotations.NotNull; + +public class ChestSortGUIHolder implements InventoryHolder { + + private Inventory inv; + + public void setInventory(Inventory inv) { + this.inv = inv; + } + + @NotNull + @Override + public Inventory getInventory() { + return inv; + } +} diff --git a/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java b/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java new file mode 100644 index 0000000..f8988ee --- /dev/null +++ b/src/main/java/de/jeff_media/chestsort/gui/GUIListener.java @@ -0,0 +1,49 @@ +package de.jeff_media.chestsort.gui; + +import de.jeff_media.chestsort.ChestSortPlugin; +import de.jeff_media.chestsort.data.PlayerSetting; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; + +public class GUIListener implements Listener { + + private static final ChestSortPlugin main = ChestSortPlugin.getInstance(); + + @EventHandler + public void onClick(InventoryClickEvent event) { + if(event.getView().getTopInventory().getHolder() instanceof ChestSortGUIHolder) { + event.setCancelled(true); + } + + ItemStack clicked = event.getCurrentItem(); + if(clicked == null || !clicked.hasItemMeta()) return; + + if(!(event.getWhoClicked() instanceof Player)) return; + Player player = (Player) event.getWhoClicked(); + PlayerSetting setting = main.getPlayerSetting(player); + String function = clicked.getItemMeta().getPersistentDataContainer().getOrDefault(new NamespacedKey(main,"function"), PersistentDataType.STRING,""); + + //System.out.println("Click in GUI: " + function); + + switch (function) { + case "": return; + case "leftclick": setting.toggleLeftClick(); break; + case "rightclick": setting.toggleRightClick(); break; + case "shiftclick": setting.toggleShiftClick(); break; + case "middleclick": setting.toggleMiddleClick(); break; + case "shiftrightclick": setting.toggleShiftRightClick(); break; + case "doubleclick": setting.toggleDoubleClick(); break; + case "outside": setting.toggleLeftClickOutside(); break; + case "autosorting": setting.toggleChestSorting(); break; + case "autoinvsorting": setting.toggleInvSorting(); break; + } + + new NewUI(player).showGUI(); + + } +} diff --git a/src/main/java/de/jeff_media/chestsort/gui/NewUI.java b/src/main/java/de/jeff_media/chestsort/gui/NewUI.java new file mode 100644 index 0000000..3c02a46 --- /dev/null +++ b/src/main/java/de/jeff_media/chestsort/gui/NewUI.java @@ -0,0 +1,73 @@ +package de.jeff_media.chestsort.gui; + +import de.jeff_media.chestsort.ChestSortPlugin; +import de.jeff_media.chestsort.enums.Hotkey; +import de.jeff_media.jefflib.ItemStackUtils; +import de.jeff_media.jefflib.TextUtils; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class NewUI { + + private static final ChestSortPlugin main = ChestSortPlugin.getInstance(); + private final YamlConfiguration conf = main.getGuiConfig(); + private final Player player; + + public NewUI(Player player) { + this.player = player; + } + + private ItemStack getItem(int slot) { + if(conf.isConfigurationSection("slots." + slot)) { + return ItemStackUtils.fromConfigurationSection(conf.getConfigurationSection("slots." + slot)); + } + if(conf.isString("slots." + slot)) { + String buttonName = conf.getString("slots." + slot); + //if(!player.hasPermission("chestsort.hotkey." + buttonName)) { + if(!Hotkey.fromPermission(buttonName).hasPermission(player)) { + buttonName = buttonName + "-nopermission"; + } else { + boolean enabled = Hotkey.fromPermission(buttonName).hasEnabled(player); + //System.out.println(buttonName + " is enabled: " + enabled); + buttonName = buttonName + (enabled ? "-enabled" : "-disabled"); + } + ItemStack button = ItemStackUtils.fromConfigurationSection(conf.getConfigurationSection("items." + buttonName)); + //System.out.println(button); + 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]); + button.setItemMeta(meta); + } + return button; + } + return null; + } + + public void showGUI() { + + NewUI gui = new NewUI(player); + + int size = conf.getInt("size"); + String title = TextUtils.format(conf.getString("title")); + + ChestSortGUIHolder holder = new ChestSortGUIHolder(); + Inventory inv = Bukkit.createInventory(holder, size, title); + holder.setInventory(inv); + + for(int i = 0; i < size; i++) { + ItemStack item = getItem(i); + inv.setItem(i, item); + } + + player.openInventory(inv); + + } + +} diff --git a/src/main/java/de/jeff_media/chestsort/listeners/Listener.java b/src/main/java/de/jeff_media/chestsort/listeners/Listener.java index 4091a28..6183d83 100644 --- a/src/main/java/de/jeff_media/chestsort/listeners/Listener.java +++ b/src/main/java/de/jeff_media/chestsort/listeners/Listener.java @@ -69,10 +69,11 @@ public class Listener implements org.bukkit.event.Listener { if(CrateReloadedHook.isCrate(clickedBlock)) { return; } - if(!ProtectionUtils.canInteract(event.getPlayer(), clickedBlock)) { - //System.out.println("ChestSort: cannot interact!"); - return; - } + if (!ProtectionUtils.canInteract(event.getPlayer(), clickedBlock, plugin.getConfig().getBoolean("mute-protection-plugins"))) { + //System.out.println("ChestSort: cannot interact!"); + return; + } + plugin.registerPlayerIfNeeded(event.getPlayer()); PlayerSetting playerSetting = plugin.getPlayerSetting(event.getPlayer()); if(!playerSetting.leftClickOutside) return; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 7bf1596..0f6be7a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -14,11 +14,14 @@ ####### Commands ####### ############################### -# /sort (or /chestsort) Toggle automatic sorting for containers (chests, barrels, enderchests, llamas, etc.) +# /sort (or /chestsort) Shows the player settings GUI # /sort on Enable automatic sorting for containers # /sort off Disable automatic sorting for containers # /sort hotkeys Open a GUI to change the sorting hotkeys # /sort help Display help about the /sort (or /chestsort) command +# /sort reload Reloads the config file +# /sort resetplayersettings Resets every player's sorting settings. You should consider +# running this after changing the default hotkey settings. # /isort (or /invsort) Sort the player's inventory # /isort hotbar Sort the player's hotbar @@ -310,6 +313,16 @@ hook-generic: true # it if it's the only possibility. prevent-sorting-null-inventories: false +##### Protection Plugins ##### +# ChestSort checks whether a player is allowed to interact with a block +# before attempting to sort a container when using the "outside"/"left-click-block" +# hotkey. This can result in messages from WorldGuard, CoreProtect, etc. being +# send to the player. To avoid this, set the following setting to true. +# This can however lead to some warnings from other plugins that do not +# properly check a Players' class before casting it to "CraftPlayer". +# Although this should NOT cause ANY problems, it's disabled by default. +mute-protection-plugins: false + ########################## ##### Sorting Method ##### ########################## diff --git a/src/main/resources/gui.yml b/src/main/resources/gui.yml new file mode 100644 index 0000000..10fd6e1 --- /dev/null +++ b/src/main/resources/gui.yml @@ -0,0 +1,292 @@ +# You can customize the GUI here. Every single item is 100% customizable, including +# their slot numbers, custom model data, custom base64 strings for heads, etc. + +# The default config uses Yaml Anchors so you don't have to define the same item +# over and over again. I wrote a tiny explanation about them here: +# https://wiki.jeff-media.com/books/general-information/page/yaml-anchors + +# Items can be defined using the following values: +# material: DIAMOND +# display-name: "My Diamond" +# lore: +# - "First line" +# - "Second line, etc." +# - "&cRed line" +# - "<#ff0000>Red hex color" +# - "<#ff0000>Hex gradient<#/ffffff>" +# amount: 1 +# base64: "" +# custom-model-data: 2 +# damage: 0 +# enchantments: +# unbreaking: 3 +# efficiency: 5 + +title: "<#000000>&l[<#007700>&lChest<#339933>&lSort<#000000>&l] &rSettings" +size: 45 +items: + autosorting-enabled: + display-name: &autosorting-name "<#2e86c1>&lAutomatic Sorting<#/85c1e9>" + material: PLAYER_HEAD + base64: &base64-enabled "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWZmMzE0MzFkNjQ1ODdmZjZlZjk4YzA2NzU4MTA2ODFmOGMxM2JmOTZmNTFkOWNiMDdlZDc4NTJiMmZmZDEifX19" + lore: + - &lore-enabled "<#229954>&lEnabled<#/7dcea0>" + - &autosorting-lore-1 "<#d5dbdb>Automatically sorts all chests," + - &autosorting-lore-2 "<#d5dbdb>barrels etc when you use them." + autosorting-disabled: + display-name: *autosorting-name + material: PLAYER_HEAD + base64: &base64-disabled "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGU0YjhiOGQyMzYyYzg2NGUwNjIzMDE0ODdkOTRkMzI3MmE2YjU3MGFmYmY4MGMyYzViMTQ4Yzk1NDU3OWQ0NiJ9fX0=" + lore: + - &lore-disabled "<#a93226>&lDisabled<#/e74c3c>" + - *autosorting-lore-1 + - *autosorting-lore-2 + autosorting-nopermission: &nopermission + display-name: *autosorting-name + material: BARRIER + lore: + - "<#a93226>No Permission<#/e74c3c>" + + + autoinvsorting-enabled: + display-name: &autoinvsorting-name "<#2e86c1>&lAutomatic Inventory Sorting<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &autoinvsorting-lore-1 "<#d5dbdb>Automatically sorts your player" + - &autoinvsorting-lore-2 "<#d5dbdb>inventory when you open it." + autoinvsorting-disabled: + display-name: *autoinvsorting-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *autoinvsorting-lore-1 + - *autoinvsorting-lore-2 + autoinvsorting-nopermission: + <<: *nopermission + display-name: *autoinvsorting-name + + + shiftclick-enabled: + display-name: &shiftclick-name "<#2e86c1>&lShift-Click<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &shiftclick-lore-1 "<#d5dbdb>Sorts an inventory using Shift-click" + - &shiftclick-lore-2 "<#d5dbdb>on an empty slot." + shiftclick-disabled: + display-name: *shiftclick-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *shiftclick-lore-1 + - *shiftclick-lore-2 + shiftclick-nopermission: + <<: *nopermission + display-name: *shiftclick-name + + + middleclick-enabled: + display-name: &middleclick-name "<#2e86c1>&lMiddle-Click<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &middleclick-lore-1 "<#d5dbdb>Sorts an inventory using Middle-click" + - &middleclick-lore-2 "<#d5dbdb>(mousewheel) on any slot." + middleclick-disabled: + display-name: *middleclick-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *middleclick-lore-1 + - *middleclick-lore-2 + middleclick-nopermission: + <<: *nopermission + display-name: *middleclick-name + + + doubleclick-enabled: + display-name: &doubleclick-name "<#2e86c1>&lDouble-Click<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &doubleclick-lore-1 "<#d5dbdb>Sorts an inventory using Double-click" + - &doubleclick-lore-2 "<#d5dbdb>on an empty slot." + doubleclick-disabled: + display-name: *doubleclick-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *doubleclick-lore-1 + - *doubleclick-lore-2 + doubleclick-nopermission: + <<: *nopermission + display-name: *doubleclick-name + + + shiftrightclick-enabled: + display-name: &shiftrightclick-name "<#2e86c1>&lShift-Right-Click<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &shiftrightclick-lore-1 "<#d5dbdb>Sorts an inventory using Shift-Right-click" + - &shiftrightclick-lore-2 "<#d5dbdb>on an empty slot." + shiftrightclick-disabled: + display-name: *shiftrightclick-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *shiftrightclick-lore-1 + - *shiftrightclick-lore-2 + shiftrightclick-nopermission: + <<: *nopermission + display-name: *shiftrightclick-name + + + outside-enabled: + display-name: &outside-name "<#2e86c1>&lLeft-Click Block<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &outside-lore-1 "<#d5dbdb>Sorts a chest, barrel etc. by" + - &outside-lore-2 "<#d5dbdb>left-clicking it." + outside-disabled: + display-name: *outside-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *outside-lore-1 + - *outside-lore-2 + outside-nopermission: + <<: *nopermission + display-name: *outside-name + + + leftclick-enabled: + display-name: &leftclick-name "<#2e86c1>&lFill Chest<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-enabled + lore: + - *lore-enabled + - &leftclick-lore-1 "<#d5dbdb>Fill a chest with matching items by" + - &leftclick-lore-2 "<#d5dbdb>left-clicking outside the opened inventory." + - &leftclick-lore-3 "<#d5dbdb>Fill a chest with all items (except your" + - &leftclick-lore-4 "<#d5dbdb>hotbar) by double-left-clicking outside" + - &leftclick-lore-5 "<#d5dbdb>the opened inventory." + leftclick-disabled: + display-name: *leftclick-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *leftclick-lore-1 + - *leftclick-lore-2 + - *leftclick-lore-3 + - *leftclick-lore-4 + - *leftclick-lore-5 + leftclick-nopermission: + <<: *nopermission + display-name: *leftclick-name + + + rightclick-enabled: + display-name: &rightclick-name "<#2e86c1>Empty Chest<#/85c1e9>" + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-enabled + - &rightclick-lore-1 "<#d5dbdb>Take matching items from a chest by" + - &rightclick-lore-2 "<#d5dbdb>right-clicking outside the opened" + - &rightclick-lore-3 "<#d5dbdb>inventory. Take all items from a chest" + - &rightclick-lore-4 "<#d5dbdb>by double-left-clicking outside the" + - &rightclick-lore-5 "<#d5dbdb>opened inventory" + rightclick-disabled: + display-name: *rightclick-name + material: PLAYER_HEAD + base64: *base64-disabled + lore: + - *lore-disabled + - *rightclick-lore-1 + - *rightclick-lore-2 + - *rightclick-lore-3 + - *rightclick-lore-4 + - *rightclick-lore-5 + rightclick-nopermission: + <<: *nopermission + display-name: *rightclick-name + + +slots: + 0: &placeholder + material: BLACK_STAINED_GLASS_PANE + display-name: "&a" # Prevents showing the item's name + 1: *placeholder + 2: *placeholder + 3: *placeholder + 4: *placeholder + 5: *placeholder + 6: *placeholder + 7: *placeholder + 8: *placeholder + + 9: *placeholder + 10: *placeholder + 11: autosorting + 12: *placeholder + 13: *placeholder + 14: *placeholder + 15: autoinvsorting + 16: *placeholder + 17: *placeholder + + 18: *placeholder + 19: shiftclick + 20: *placeholder + 21: middleclick + 22: *placeholder + 23: doubleclick + 24: *placeholder + 25: shiftrightclick + 26: *placeholder + + 27: *placeholder + 28: *placeholder + 29: leftclick + 30: *placeholder + 31: outside + 32: *placeholder + 33: rightclick + 34: *placeholder + 35: *placeholder + + 36: *placeholder + 37: *placeholder + 38: *placeholder + 39: *placeholder + 40: *placeholder + 41: *placeholder + 42: *placeholder + 43: *placeholder + 44: *placeholder + + 45: *placeholder + 46: *placeholder + 47: *placeholder + 48: *placeholder + 49: *placeholder + 50: *placeholder + 51: *placeholder + 52: *placeholder + 53: *placeholder \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 020339c..45965e8 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -15,11 +15,12 @@ commands: sort: description: Toggle automatic chest sorting or change your hotkey settings usage: | - / -- Toggle automatic chest sorting + / -- Shows the player setting GUI / on -- Enable automatic chest sorting / off -- Disable automatic chest sorting - / hotkeys -- Change your hotkey settings + / toggle -- Toggle automatic chest sorting / reload -- Reloads config + / resetplayersettings -- Resets all players' sorting settings / help -- Shows help about this command aliases: chestsort permission: chestsort.use @@ -35,11 +36,6 @@ commands: / help -- Shows help about this command aliases: [invsort,inventorysort] permission: chestsort.use.inventory - chestsortadmin: - description: Admin command for ChestSort - usage: | - / reset -- Reset's a player's hotkey settings - permission: chestsort.admin permissions: chestsort.use: description: Allows chest sorting @@ -47,6 +43,8 @@ permissions: description: Allows inventory sorting chestsort.reload: description: Allows to reload the config via /chestsort reload + chestsort.resetplayersettings: + description: Allows to reset every player's sorting settings chestsort.hotkey.shiftclick: default: true chestsort.hotkey.middleclick: diff --git a/src/main/resources/settings.fingerprint b/src/main/resources/settings.fingerprint new file mode 100644 index 0000000..ae13e8c --- /dev/null +++ b/src/main/resources/settings.fingerprint @@ -0,0 +1 @@ +v: 0 \ No newline at end of file