This commit is contained in:
mfnalex 2021-10-09 19:46:07 +02:00
parent ab52b289c9
commit c700ccbe70
14 changed files with 669 additions and 49 deletions

View File

@ -1,6 +1,17 @@
# Changelog # 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 - Fixed furnaces being sortable using the left-click hotkey
## 11.5.4 ## 11.5.4

View File

@ -9,7 +9,7 @@
<name>ChestSort</name> <name>ChestSort</name>
<url>https://www.chestsort.de</url> <url>https://www.chestsort.de</url>
<description>Allows automatic chest sorting!</description> <description>Allows automatic chest sorting!</description>
<version>11.5.5</version> <version>12.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>

View File

@ -37,6 +37,8 @@ import de.jeff_media.chestsort.config.ConfigUpdater;
import de.jeff_media.chestsort.config.Messages; import de.jeff_media.chestsort.config.Messages;
import de.jeff_media.chestsort.data.Category; import de.jeff_media.chestsort.data.Category;
import de.jeff_media.chestsort.data.PlayerSetting; 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.gui.SettingsGUI;
import de.jeff_media.chestsort.handlers.ChestSortOrganizer; import de.jeff_media.chestsort.handlers.ChestSortOrganizer;
import de.jeff_media.chestsort.handlers.ChestSortPermissionsHandler; import de.jeff_media.chestsort.handlers.ChestSortPermissionsHandler;
@ -56,11 +58,13 @@ import io.papermc.lib.PaperLib;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.yaml.snakeyaml.Yaml;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
@ -95,11 +99,15 @@ public class ChestSortPlugin extends JavaPlugin {
private UpdateChecker updateChecker; private UpdateChecker updateChecker;
private boolean usingMatchingConfig = true; private boolean usingMatchingConfig = true;
private boolean verbose = true; private boolean verbose = true;
private YamlConfiguration guiConfig = new YamlConfiguration();
private int settingsFingerprint = 0;
public static ChestSortPlugin getInstance() { public static ChestSortPlugin getInstance() {
return instance; return instance;
} }
public YamlConfiguration getGuiConfig() { return guiConfig; }
public static double getUpdateCheckInterval() { public static double getUpdateCheckInterval() {
return updateCheckInterval; 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 // This saves the config.yml included in the .jar file, but it will not
// overwrite an existing config.yml // overwrite an existing config.yml
this.saveDefaultConfig(); this.saveDefaultConfig();
createGUIConfig();
reloadConfig(); reloadConfig();
// Load disabled-worlds. If it does not exist in the config, it returns null. // 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() { private void createDirectories() {
// Create a playerdata folder that contains all the perPlayerSettings as .yml // Create a playerdata folder that contains all the perPlayerSettings as .yml
File playerDataFolder = new File(getDataFolder().getPath() + File.separator + "playerdata"); File playerDataFolder = new File(getDataFolder().getPath() + File.separator + "playerdata");
@ -411,6 +428,13 @@ public class ChestSortPlugin extends JavaPlugin {
public void load(boolean reload) { 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) { if (reload) {
unregisterAllPlayers(); unregisterAllPlayers();
reloadConfig(); reloadConfig();
@ -477,6 +501,7 @@ public class ChestSortPlugin extends JavaPlugin {
setEnderContainersHook(new EnderContainersHook(this)); setEnderContainersHook(new EnderContainersHook(this));
getServer().getPluginManager().registerEvents(getListener(), this); getServer().getPluginManager().registerEvents(getListener(), this);
getServer().getPluginManager().registerEvents(getSettingsGUI(), this); getServer().getPluginManager().registerEvents(getSettingsGUI(), this);
getServer().getPluginManager().registerEvents(new GUIListener(), this);
ChestSortCommand chestsortCommandExecutor = new ChestSortCommand(this); ChestSortCommand chestsortCommandExecutor = new ChestSortCommand(this);
TabCompleter tabCompleter = new TabCompleter(); TabCompleter tabCompleter = new TabCompleter();
this.getCommand("sort").setExecutor(chestsortCommandExecutor); this.getCommand("sort").setExecutor(chestsortCommandExecutor);
@ -484,7 +509,7 @@ public class ChestSortPlugin extends JavaPlugin {
InvSortCommand invsortCommandExecutor = new InvSortCommand(this); InvSortCommand invsortCommandExecutor = new InvSortCommand(this);
this.getCommand("invsort").setExecutor(invsortCommandExecutor); this.getCommand("invsort").setExecutor(invsortCommandExecutor);
this.getCommand("invsort").setTabCompleter(tabCompleter); this.getCommand("invsort").setTabCompleter(tabCompleter);
this.getCommand("chestsortadmin").setExecutor(new AdminCommand(this)); //this.getCommand("chestsortadmin").setExecutor(new AdminCommand(this));
if (isVerbose()) { if (isVerbose()) {
getLogger().info("Use permissions: " + getConfig().getBoolean("use-permissions")); getLogger().info("Use permissions: " + getConfig().getBoolean("use-permissions"));
@ -546,9 +571,12 @@ public class ChestSortPlugin extends JavaPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
// We have to unregister every player to save their perPlayerSettings // We have to unregister every player to save their perPlayerSettings
for (Player p : getServer().getOnlinePlayers()) { for (Player player : getServer().getOnlinePlayers()) {
unregisterPlayer(p); if(player.getOpenInventory().getTopInventory().getHolder() instanceof ChestSortGUIHolder) {
getPermissionsHandler().removePermissions(p); 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) { public void registerPlayerIfNeeded(Player p) {
// Players are stored by their UUID, so that name changes don't break player's // Players are stored by their UUID, so that name changes don't break player's
// settings // settings
@ -685,16 +725,19 @@ public class ChestSortPlugin extends JavaPlugin {
} else { } else {
// If the file exists, check if the player has sorting enabled // If the file exists, check if the player has sorting enabled
// NBT Values // 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"))))); String fingerprint = getFingerprint();
middleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "middleClick", String.valueOf(playerConfig.getBoolean("middleClick"))));
shiftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftClick", String.valueOf(playerConfig.getBoolean("shiftClick")))); activeForThisPlayer = Boolean.parseBoolean(NBTAPI.getNBT(p, "sortingEnabled" + fingerprint, String.valueOf(playerConfig.getBoolean("sortingEnabled"))));
doubleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "doubleClick", String.valueOf(playerConfig.getBoolean("doubleClick")))); invActiveForThisPlayer = Boolean.parseBoolean(NBTAPI.getNBT(p, "invSortingEnabled" + fingerprint, String.valueOf(playerConfig.getBoolean("invSortingEnabled", getConfig().getBoolean("inv-sorting-enabled-by-default")))));
shiftRightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftRightClick", String.valueOf(playerConfig.getBoolean("shiftRightClick")))); middleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "middleClick" + fingerprint, String.valueOf(playerConfig.getBoolean("middleClick"))));
leftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "leftClick", String.valueOf(playerConfig.getBoolean("leftClick", getConfig().getBoolean("additional-hotkeys.left-click"))))); shiftClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftClick" + fingerprint, String.valueOf(playerConfig.getBoolean("shiftClick"))));
rightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "rightClick", String.valueOf(playerConfig.getBoolean("rightClick", getConfig().getBoolean("additional-hotkeys.right-click"))))); doubleClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "doubleClick" + fingerprint, String.valueOf(playerConfig.getBoolean("doubleClick"))));
leftClickFromOutside = Boolean.parseBoolean(NBTAPI.getNBT(p, "leftClickOutside", String.valueOf(playerConfig.getBoolean("leftClickOutside", getConfig().getBoolean("left-click-to-sort-enabled-by-default"))))); shiftRightClick = Boolean.parseBoolean(NBTAPI.getNBT(p, "shiftRightClick" + fingerprint, String.valueOf(playerConfig.getBoolean("shiftRightClick"))));
hasSeenMessage = Boolean.parseBoolean(NBTAPI.getNBT(p, "hasSeenMessage", String.valueOf("false"))); 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"); //System.out.println("Loading playersetting from NBT");
if(getConfig().getBoolean("show-message-again-after-logout")) { if(getConfig().getBoolean("show-message-again-after-logout")) {
//System.out.println("show-message-again-after-logout is true, sooo..."); //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 // Saves default category files, when enabled in the config
private void saveDefaultCategories() { private void saveDefaultCategories() {
@ -837,6 +888,8 @@ public class ChestSortPlugin extends JavaPlugin {
getConfig().addDefault("hook-generic", true); getConfig().addDefault("hook-generic", true);
getConfig().addDefault("prevent-sorting-null-inventories", false); getConfig().addDefault("prevent-sorting-null-inventories", false);
getConfig().addDefault("mute-protection-plugins", false);
getConfig().addDefault("verbose", true); // Prints some information in onEnable() 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()); PlayerSetting setting = getPerPlayerSettings().get(p.getUniqueId().toString());
if (McVersion.isAtLeast(1,14,4)) { if (McVersion.isAtLeast(1,14,4)) {
NBTAPI.addNBT(p, "sortingEnabled", String.valueOf(setting.sortingEnabled));
NBTAPI.addNBT(p, "invSortingEnabled", String.valueOf(setting.invSortingEnabled)); for(NamespacedKey key : p.getPersistentDataContainer().getKeys()) {
NBTAPI.addNBT(p, "hasSeenMessage", String.valueOf(setting.hasSeenMessage)); if(key.getKey().equals(new NamespacedKey(this,"test").getKey())) {
NBTAPI.addNBT(p, "middleClick", String.valueOf(setting.middleClick)); p.getPersistentDataContainer().remove(key);
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)); String fingerprint = getFingerprint();
NBTAPI.addNBT(p, "rightClick", String.valueOf(setting.rightClick));
NBTAPI.addNBT(p, "leftClickOutside", String.valueOf(setting.leftClickOutside)); 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 { } else {
File playerFile = new File(getDataFolder() + File.separator + "playerdata", p.getUniqueId() + ".yml"); File playerFile = new File(getDataFolder() + File.separator + "playerdata", p.getUniqueId() + ".yml");

View File

@ -3,8 +3,10 @@ package de.jeff_media.chestsort.commands;
import de.jeff_media.chestsort.ChestSortPlugin; import de.jeff_media.chestsort.ChestSortPlugin;
import de.jeff_media.chestsort.config.Messages; import de.jeff_media.chestsort.config.Messages;
import de.jeff_media.chestsort.data.PlayerSetting; import de.jeff_media.chestsort.data.PlayerSetting;
import de.jeff_media.chestsort.gui.NewUI;
import de.jeff_media.chestsort.handlers.Debugger; import de.jeff_media.chestsort.handlers.Debugger;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -40,6 +42,17 @@ public class ChestSortCommand implements CommandExecutor {
return true; 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 // Reload command
if (args.length > 0 && args[0].equalsIgnoreCase("reload")) { if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
if (!sender.hasPermission("chestsort.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(!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 // Settings GUI
if (args.length > 0) { /*if (args.length > 0) {
if (args[0].equalsIgnoreCase("hotkey") || args[0].equalsIgnoreCase("hotkeys")) { if (args[0].equalsIgnoreCase("hotkey") || args[0].equalsIgnoreCase("hotkeys")) {
if (!plugin.isHotkeyGUI()) { if (!plugin.isHotkeyGUI()) {
@ -106,7 +124,7 @@ public class ChestSortCommand implements CommandExecutor {
return true; return true;
} }
} }*/
// Settings GUI End // Settings GUI End
PlayerSetting setting = plugin.getPerPlayerSettings().get(p.getUniqueId().toString()); 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\"")); p.sendMessage(String.format(Messages.MSG_INVALIDOPTIONS, "\"" + args[0] + "\"", "\"toggle\", \"on\", \"off\", \"hotkeys\""));
return true; return true;
} }
if (args.length == 0 || args[0].equalsIgnoreCase("toggle")) {
setting.toggleChestSorting(); if(args.length > 0) {
} else if (args[0].equalsIgnoreCase("on")) { if (args[0].equalsIgnoreCase("toggle")) {
setting.enableChestSorting(); setting.toggleChestSorting();
} else if (args[0].equalsIgnoreCase("off")) { } else if (args[0].equalsIgnoreCase("on")) {
setting.disableChestSorting(); setting.enableChestSorting();
} else if (args[0].equalsIgnoreCase("off")) {
setting.disableChestSorting();
}
} }
setting.hasSeenMessage = true; setting.hasSeenMessage = true;
if (setting.sortingEnabled) { /*if (setting.sortingEnabled) {
p.sendMessage(Messages.MSG_ACTIVATED); p.sendMessage(Messages.MSG_ACTIVATED);
} else { } else {
p.sendMessage(Messages.MSG_DEACTIVATED); p.sendMessage(Messages.MSG_DEACTIVATED);
} }*/
new NewUI(p).showGUI();
return true; return true;
} }

View File

@ -37,7 +37,14 @@ public class TabCompleter implements org.bukkit.command.TabCompleter {
entered = args[args.length-1]; entered = args[args.length-1];
} }
if(command.getName().equalsIgnoreCase("sort")) { if(command.getName().equalsIgnoreCase("sort")) {
return getMatchingOptions(entered,chestsortOptions); List<String> 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")) { if(command.getName().equalsIgnoreCase("invsort")) {
return getMatchingOptions(entered,invsortOptions); return getMatchingOptions(entered,invsortOptions);

View File

@ -1,16 +1,86 @@
package de.jeff_media.chestsort.enums; 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; import java.util.Locale;
public enum Hotkey { public enum Hotkey {
AUTO_SORT, AUTO_INV_SORT,
SHIFT_CLICK, SHIFT_CLICK,
MIDDLE_CLICK, DOUBLE_CLICK, SHIFT_RIGHT_CLICK, MIDDLE_CLICK, DOUBLE_CLICK, SHIFT_RIGHT_CLICK,
OUTSIDE, LEFT_CLICK, 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) { 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("_", ""); String permission = "chestsort.hotkey." + hotkey.name().toLowerCase(Locale.ROOT).replace("_", "");
//System.out.println("Permission for " + hotkey.name()+ ": " + permission); //System.out.println("Permission for " + hotkey.name()+ ": " + permission);
return 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;
}
}
} }

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -69,10 +69,11 @@ public class Listener implements org.bukkit.event.Listener {
if(CrateReloadedHook.isCrate(clickedBlock)) { if(CrateReloadedHook.isCrate(clickedBlock)) {
return; return;
} }
if(!ProtectionUtils.canInteract(event.getPlayer(), clickedBlock)) { if (!ProtectionUtils.canInteract(event.getPlayer(), clickedBlock, plugin.getConfig().getBoolean("mute-protection-plugins"))) {
//System.out.println("ChestSort: cannot interact!"); //System.out.println("ChestSort: cannot interact!");
return; return;
} }
plugin.registerPlayerIfNeeded(event.getPlayer()); plugin.registerPlayerIfNeeded(event.getPlayer());
PlayerSetting playerSetting = plugin.getPlayerSetting(event.getPlayer()); PlayerSetting playerSetting = plugin.getPlayerSetting(event.getPlayer());
if(!playerSetting.leftClickOutside) return; if(!playerSetting.leftClickOutside) return;

View File

@ -14,11 +14,14 @@
####### Commands ####### ####### 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 on Enable automatic sorting for containers
# /sort off Disable automatic sorting for containers # /sort off Disable automatic sorting for containers
# /sort hotkeys Open a GUI to change the sorting hotkeys # /sort hotkeys Open a GUI to change the sorting hotkeys
# /sort help Display help about the /sort (or /chestsort) command # /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 (or /invsort) Sort the player's inventory
# /isort hotbar Sort the player's hotbar # /isort hotbar Sort the player's hotbar
@ -310,6 +313,16 @@ hook-generic: true
# it if it's the only possibility. # it if it's the only possibility.
prevent-sorting-null-inventories: false 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 ##### ##### Sorting Method #####
########################## ##########################

292
src/main/resources/gui.yml Normal file
View File

@ -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: "<base64 string for player heads>"
# 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

View File

@ -15,11 +15,12 @@ commands:
sort: sort:
description: Toggle automatic chest sorting or change your hotkey settings description: Toggle automatic chest sorting or change your hotkey settings
usage: | usage: |
/<command> -- Toggle automatic chest sorting /<command> -- Shows the player setting GUI
/<command> on -- Enable automatic chest sorting /<command> on -- Enable automatic chest sorting
/<command> off -- Disable automatic chest sorting /<command> off -- Disable automatic chest sorting
/<command> hotkeys -- Change your hotkey settings /<command> toggle -- Toggle automatic chest sorting
/<command> reload -- Reloads config /<command> reload -- Reloads config
/<command> resetplayersettings -- Resets all players' sorting settings
/<command> help -- Shows help about this command /<command> help -- Shows help about this command
aliases: chestsort aliases: chestsort
permission: chestsort.use permission: chestsort.use
@ -35,11 +36,6 @@ commands:
/<command> help -- Shows help about this command /<command> help -- Shows help about this command
aliases: [invsort,inventorysort] aliases: [invsort,inventorysort]
permission: chestsort.use.inventory permission: chestsort.use.inventory
chestsortadmin:
description: Admin command for ChestSort
usage: |
/<command> reset <player> -- Reset's a player's hotkey settings
permission: chestsort.admin
permissions: permissions:
chestsort.use: chestsort.use:
description: Allows chest sorting description: Allows chest sorting
@ -47,6 +43,8 @@ permissions:
description: Allows inventory sorting description: Allows inventory sorting
chestsort.reload: chestsort.reload:
description: Allows to reload the config via /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: chestsort.hotkey.shiftclick:
default: true default: true
chestsort.hotkey.middleclick: chestsort.hotkey.middleclick:

View File

@ -0,0 +1 @@
v: 0