diff --git a/CHANGELOG.md b/CHANGELOG.md
index eba7cf7..f6115a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## 9.3.0
+- Added CraftBukkit compatibility (although I don't unterstand why anyone would prefer CraftBukkit over Spigot)
+
+## 9.2.0
+- Added support for PlayerVaultsX
+
## 9.1.1
- Fixed category files being "too wildcardy" lol
diff --git a/pom.xml b/pom.xml
index 9e8cc47..d410a71 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
ChestSort
https://www.chestsort.de
Automatically sorts your chests!
- 9.1.1
+ 9.3.0
jar
@@ -51,6 +51,10 @@
org.bstats
de.jeff_media.ChestSort
+
+ io.papermc.lib
+ de.jeff_media.ChestSort.paperlib
+
@@ -85,6 +89,10 @@
spigot-repo
https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+ papermc
+ https://papermc.io/repo/repository/maven-public/
+
placeholderapi
https://repo.extendedclip.com/content/repositories/placeholderapi/
@@ -179,6 +187,12 @@
RC-15
provided
+
+ io.papermc
+ paperlib
+ 1.0.6
+ compile
+
diff --git a/src/main/java/de/jeff_media/ChestSort/ChestSortDebugger.java b/src/main/java/de/jeff_media/ChestSort/ChestSortDebugger.java
index 3613a60..4da078f 100644
--- a/src/main/java/de/jeff_media/ChestSort/ChestSortDebugger.java
+++ b/src/main/java/de/jeff_media/ChestSort/ChestSortDebugger.java
@@ -1,38 +1,40 @@
package de.jeff_media.ChestSort;
import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
public class ChestSortDebugger implements @NotNull Listener {
-
- private final ChestSortPlugin plugin;
- ChestSortDebugger(ChestSortPlugin plugin) {
- plugin.getLogger().warning("=======================================");
- plugin.getLogger().warning(" CHESTSORT DEBUG MODE ACTIVATED!");
- plugin.getLogger().warning("Only use this for development purposes!");
- plugin.getLogger().warning("=======================================");
- this.plugin=plugin;
- }
-
- @EventHandler
- public void onInventoryClickEvent(InventoryClickEvent e) {
- // Debug
- if(plugin.debug) {
- System.out.println(" ");
- System.out.println("InventoryClickEvent:");
- System.out.println("- Holder: " + e.getInventory().getHolder());
- if(e.getInventory().getHolder()!=null) {
- System.out.println("- Holder class: "+e.getInventory().getHolder().getClass());
+ private final ChestSortPlugin plugin;
+
+ ChestSortDebugger(ChestSortPlugin plugin) {
+ plugin.getLogger().warning("=======================================");
+ plugin.getLogger().warning(" CHESTSORT DEBUG MODE ACTIVATED!");
+ plugin.getLogger().warning("Only use this for development purposes!");
+ plugin.getLogger().warning("=======================================");
+ this.plugin = plugin;
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onInventoryClickEvent(InventoryClickEvent e) {
+ if(plugin.debug) {
+ // Debug
+ plugin.debug(" ");
+ plugin.debug("InventoryClickEvent:");
+ plugin.debug("- Holder: " + e.getInventory().getHolder());
+ if (e.getInventory().getHolder() != null) {
+ plugin.debug("- Holder class: " + e.getInventory().getHolder().getClass());
}
- System.out.println("- Slot: "+e.getRawSlot());
- System.out.println("- Left-Click: "+e.isLeftClick());
- System.out.println("- Right-Click: "+e.isRightClick());
- System.out.println("- Shift-Click: "+e.isShiftClick());
- System.out.println(" ");
+ plugin.debug("- Slot: " + e.getRawSlot());
+ plugin.debug("- Left-Click: " + e.isLeftClick());
+ plugin.debug("- Right-Click: " + e.isRightClick());
+ plugin.debug("- Shift-Click: " + e.isShiftClick());
+ plugin.debug(" ");
}
- }
+
+ }
}
diff --git a/src/main/java/de/jeff_media/ChestSort/ChestSortListener.java b/src/main/java/de/jeff_media/ChestSort/ChestSortListener.java
index 2ddc688..c83c161 100644
--- a/src/main/java/de/jeff_media/ChestSort/ChestSortListener.java
+++ b/src/main/java/de/jeff_media/ChestSort/ChestSortListener.java
@@ -1,9 +1,6 @@
package de.jeff_media.ChestSort;
-import de.jeff_media.ChestSort.hooks.CrateReloadedHook;
-import de.jeff_media.ChestSort.hooks.GoldenCratesHook;
-import de.jeff_media.ChestSort.hooks.HeadDatabaseHook;
-import de.jeff_media.ChestSort.hooks.MinepacksHook;
+import de.jeff_media.ChestSort.hooks.*;
import de.jeff_media.ChestSort.utils.LlamaUtils;
import de.jeff_media.ChestSortAPI.ChestSortEvent;
import de.jeff_media.ChestSortAPI.ISortable;
@@ -354,36 +351,48 @@ public class ChestSortListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onHotkey(InventoryClickEvent event) {
+ plugin.debug2("Hotkey?");
+
if (!(event.getWhoClicked() instanceof Player)) {
+ plugin.debug2("exit: 0");
return;
}
+
Player p = (Player) event.getWhoClicked();
plugin.registerPlayerIfNeeded(p);
if (!plugin.getConfig().getBoolean("allow-sorting-hotkeys")) {
+ plugin.debug2("exit: 1");
return;
}
+
if (!p.hasPermission("chestsort.use") && !p.hasPermission("chestsort.use.inventory")) {
+ plugin.debug2("exit: 2");
return;
}
+
//InventoryHolder holder = event.getInventory().getHolder();
if (event.getClickedInventory() == null) {
+ plugin.debug2("exit: 3");
return;
}
+
boolean isAPICall = isAPICall(event.getClickedInventory());
// Detect generic GUIs
if(!isAPICall &&
(plugin.genericHook.isPluginGUI(event.getInventory())
|| plugin.genericHook.isPluginGUI(event.getInventory()))) {
+ plugin.debug("Aborting hotkey sorting: no API call & generic GUI detected");
return;
}
+
// Possible fix for #57
if (!isAPICall && (event.getClickedInventory().getHolder() != null
&& event.getClickedInventory().getHolder() == p
@@ -392,6 +401,7 @@ public class ChestSortListener implements Listener {
return;
}
+
// End Possible fix for #57
InventoryHolder holder = event.getClickedInventory().getHolder();
@@ -405,12 +415,14 @@ public class ChestSortListener implements Listener {
return;
}
+
// Prevent player from putting items into GUI inventory
if (event.getInventory() == setting.guiInventory) {
event.setCancelled(true);
return;
}
+
switch (event.getClick()) {
case MIDDLE:
cause = ChestSortLogger.SortCause.H_MIDDLE;
@@ -426,6 +438,7 @@ public class ChestSortListener implements Listener {
}
break;
case DOUBLE_CLICK:
+ if(event.isShiftClick()) return;
cause = ChestSortLogger.SortCause.H_DOUBLE;
//if(plugin.getConfig().getBoolean("hotkeys.double-click")) {
if (setting.doubleClick) {
@@ -461,23 +474,40 @@ public class ChestSortListener implements Listener {
return;
}
- if (isAPICall || belongsToChestLikeBlock(event.getClickedInventory()) || LlamaUtils.belongsToLlama(event.getClickedInventory()) || minepacksHook.isMinepacksBackpack(event.getClickedInventory())) {
+
+ if(plugin.isInHotkeyCooldown(p.getUniqueId())) {
+ plugin.debug("Skipping: hotkey cooldown");
+ return;
+ }
+
+
+ plugin.debug("Hotkey triggered: " + event.getClick().name());
+
+ if (isAPICall
+ || belongsToChestLikeBlock(event.getClickedInventory())
+ || LlamaUtils.belongsToLlama(event.getClickedInventory())
+ || minepacksHook.isMinepacksBackpack(event.getClickedInventory())
+ || plugin.playerVaultsHook.isPlayerVault(event.getClickedInventory())) {
+
if (!p.hasPermission("chestsort.use")) {
return;
}
if (LlamaUtils.belongsToLlama(event.getClickedInventory())) {
+
plugin.lgr.logSort(p,cause);
ChestedHorse llama = (ChestedHorse) event.getInventory().getHolder();
plugin.organizer.sortInventory(event.getClickedInventory(), 2, LlamaUtils.getLlamaChestSize(llama) + 1);
plugin.organizer.updateInventoryView(event);
return;
}
+
plugin.lgr.logSort(p,cause);
plugin.organizer.sortInventory(event.getClickedInventory());
plugin.organizer.updateInventoryView(event);
} else if (holder instanceof Player) {
+
if (!p.hasPermission("chestsort.use.inventory")) {
return;
}
@@ -486,10 +516,12 @@ public class ChestSortListener implements Listener {
plugin.lgr.logSort(p,cause);
plugin.organizer.sortInventory(p.getInventory(), 0, 8);
plugin.organizer.updateInventoryView(event);
+
} else if (event.getSlotType() == SlotType.CONTAINER) {
plugin.lgr.logSort(p,cause);
plugin.organizer.sortInventory(p.getInventory(), 9, 35);
plugin.organizer.updateInventoryView(event);
+
}
}
}
diff --git a/src/main/java/de/jeff_media/ChestSort/ChestSortOrganizer.java b/src/main/java/de/jeff_media/ChestSort/ChestSortOrganizer.java
index 46ee092..10a291f 100644
--- a/src/main/java/de/jeff_media/ChestSort/ChestSortOrganizer.java
+++ b/src/main/java/de/jeff_media/ChestSort/ChestSortOrganizer.java
@@ -460,8 +460,10 @@ public class ChestSortOrganizer {
// Sort an inventory only between startSlot and endSlot
void sortInventory(@NotNull Inventory inv, int startSlot, int endSlot) {
if(inv==null) return;
+ plugin.debug("Attempting to sort an Inventory and calling ChestSortEvent.");
Class extends Inventory> invClass = inv.getClass();
de.jeff_media.ChestSortAPI.ChestSortEvent chestSortEvent = new de.jeff_media.ChestSortAPI.ChestSortEvent(inv);
+
try {
if (invClass.getMethod("getLocation", null) != null) {
// This whole try/catch fixes MethodNotFoundException when using inv.getLocation in Spigot 1.8.
@@ -490,6 +492,7 @@ public class ChestSortOrganizer {
Bukkit.getPluginManager().callEvent(chestSortEvent);
if (chestSortEvent.isCancelled()) {
+ plugin.debug("ChestSortEvent cancelled, I'll stay in bed.");
return;
}
@@ -597,6 +600,7 @@ public class ChestSortOrganizer {
inv.setItem(currentSlot, item);
currentSlot++;
}
+ plugin.debug("Sorting successful. I'll go back to bed now.");
}
public void updateInventoryView(InventoryClickEvent event) {
diff --git a/src/main/java/de/jeff_media/ChestSort/ChestSortPlugin.java b/src/main/java/de/jeff_media/ChestSort/ChestSortPlugin.java
index a312487..d2441be 100644
--- a/src/main/java/de/jeff_media/ChestSort/ChestSortPlugin.java
+++ b/src/main/java/de/jeff_media/ChestSort/ChestSortPlugin.java
@@ -41,9 +41,12 @@ import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
+import de.jeff_media.ChestSort.config.Config;
import de.jeff_media.ChestSort.hooks.GenericGUIHook;
+import de.jeff_media.ChestSort.hooks.PlayerVaultsHook;
import de.jeff_media.ChestSort.placeholders.ChestSortPlaceholders;
import de.jeff_media.PluginUpdateChecker.PluginUpdateChecker;
+import io.papermc.lib.PaperLib;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -61,6 +64,7 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
ChestSortLogger lgr;
Map perPlayerSettings = new HashMap<>();
+ HashMap hotkeyCooldown;
ChestSortMessages messages;
ChestSortOrganizer organizer;
PluginUpdateChecker updateChecker;
@@ -70,7 +74,7 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
String sortingMethod;
ArrayList disabledWorlds;
ChestSortAPIHandler api;
- final int currentConfigVersion = 44;
+ final int currentConfigVersion = 45;
boolean usingMatchingConfig = true;
protected boolean debug = false;
boolean verbose = true;
@@ -81,6 +85,7 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
public boolean hookMinepacks = false;
public GenericGUIHook genericHook;
+ public PlayerVaultsHook playerVaultsHook;
private static long updateCheckInterval = 4*60*60; // in seconds. We check on startup and every 4 hours
@@ -133,6 +138,10 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
if(debug) getLogger().warning("[DEBUG] "+t);
}
+ public void debug2(String t) {
+ if(getConfig().getBoolean(Config.DEBUG2)) getLogger().warning("[DEBUG2] "+t);
+ }
+
// Creates the default configuration file
// Also checks the config-version of an already existing file. If the existing
// config is too
@@ -490,12 +499,26 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
messages = new ChestSortMessages(this);
organizer = new ChestSortOrganizer(this);
settingsGUI = new ChestSortSettingsGUI(this);
- updateChecker = new PluginUpdateChecker(this, "https://api.jeff-media.de/chestsort/chestsort-latest-version.txt", "https://chestsort.de", "https://chestsort.de/changelog", "https://chestsort.de/donate");
+ try {
+ if(Class.forName("net.md_5.bungee.api.chat.BaseComponent") != null) {
+ updateChecker = new PluginUpdateChecker(this, "https://api.jeff-media.de/chestsort/chestsort-latest-version.txt", "https://chestsort.de", "https://chestsort.de/changelog", "https://chestsort.de/donate");
+ } 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);
+ }
listener = new ChestSortListener(this);
api = new ChestSortAPIHandler(this);
+ hotkeyCooldown = new HashMap<>();
permissionsHandler = new ChestSortPermissionsHandler(this);
updateCheckInterval = (int) (getConfig().getDouble("check-interval")*60*60);
sortingMethod = getConfig().getString("sorting-method");
+ playerVaultsHook = new PlayerVaultsHook(this);
getServer().getPluginManager().registerEvents(listener, this);
getServer().getPluginManager().registerEvents(settingsGUI, this);
ChestSortChestSortCommand chestsortCommandExecutor = new ChestSortChestSortCommand(this);
@@ -536,11 +559,13 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
getLogger().info("Categories: " + getCategoryList());
}
- if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("true")) {
- updateChecker.check(updateCheckInterval);
- } // When set to on-startup, we check right now (delay 0)
- else if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("on-startup")) {
- updateChecker.check();
+ if(updateChecker!=null) {
+ if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("true")) {
+ updateChecker.check(updateCheckInterval);
+ } // When set to on-startup, we check right now (delay 0)
+ else if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("on-startup")) {
+ updateChecker.check();
+ }
}
registerMetrics();
@@ -590,6 +615,17 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
}
+ public boolean isInHotkeyCooldown(UUID uuid) {
+ double cooldown = getConfig().getDouble(Config.HOTKEY_COOLDOWN)*1000;
+ if(cooldown==0) return false;
+ long lastUsage = hotkeyCooldown.containsKey(uuid) ? hotkeyCooldown.get(uuid) : 0;
+ long currentTime = System.currentTimeMillis();
+ long difference = currentTime-lastUsage;
+ hotkeyCooldown.put(uuid,currentTime);
+ debug("Difference: "+difference);
+ return difference <= cooldown;
+ }
+
void registerPlayerIfNeeded(Player p) {
// Players are stored by their UUID, so that name changes don't break player's
// settings
diff --git a/src/main/java/de/jeff_media/ChestSort/config/Config.java b/src/main/java/de/jeff_media/ChestSort/config/Config.java
new file mode 100644
index 0000000..85d9d2d
--- /dev/null
+++ b/src/main/java/de/jeff_media/ChestSort/config/Config.java
@@ -0,0 +1,17 @@
+package de.jeff_media.ChestSort.config;
+
+import de.jeff_media.ChestSort.ChestSortPlugin;
+
+public class Config {
+ public static final String HOTKEY_COOLDOWN = "hotkey-cooldown";
+ public static final String DEBUG2 = "debug2";
+
+ private final ChestSortPlugin main;
+
+ public Config(ChestSortPlugin main) {
+ this.main=main;
+
+ main.getConfig().addDefault(HOTKEY_COOLDOWN,0.0);
+ main.getConfig().addDefault(DEBUG2,false);
+ }
+}
diff --git a/src/main/java/de/jeff_media/ChestSort/hooks/PlayerVaultsHook.java b/src/main/java/de/jeff_media/ChestSort/hooks/PlayerVaultsHook.java
new file mode 100644
index 0000000..f8784c9
--- /dev/null
+++ b/src/main/java/de/jeff_media/ChestSort/hooks/PlayerVaultsHook.java
@@ -0,0 +1,20 @@
+package de.jeff_media.ChestSort.hooks;
+
+import de.jeff_media.ChestSort.ChestSortPlugin;
+import org.bukkit.inventory.Inventory;
+
+public class PlayerVaultsHook {
+
+ private final ChestSortPlugin main;
+
+ public PlayerVaultsHook(ChestSortPlugin main) {
+ this.main=main;
+ }
+
+ public boolean isPlayerVault(Inventory inv) {
+ if(inv==null) return false;
+ if(inv.getHolder()==null) return false;
+ if(!main.getConfig().getBoolean("hook-playervaultsx",true)) return false;
+ return inv.getHolder().getClass().getName().equals("com.drtshock.playervaults.vaultmanagement.VaultHolder");
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 5ba598e..9947137 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -145,6 +145,10 @@ sorting-hotkeys:
# Use shift + right-click on any EMPTY inventory slot as hotkey
shift-right-click: true
+# Amount in seconds that players have to wait between using hotkeys to prevent them from spamming the
+# sorting mechanism
+hotkey-cooldown: 0.2
+
# Additionally to sorting hotkeys, you can quickly unload your inventory into a chest and vice versa
# using left-click or right-click outside of a chest's inventory.
# A single click will only affect matching items (items that are already present in the other inventory)
@@ -225,6 +229,11 @@ hook-inventorypages: true
# backpacks and sort them like a regular chest.
hook-minepacks: true
+##### PlayerVaultsX #####
+# When PlayerVaultsX is installed, ChestSort can sort your
+# player vaults just like regular chests.
+hook-playervaultsx: true
+
##### CrateReloaded #####
# Prevents the player from using hotkeys on a crate
hook-cratereloaded: true
@@ -642,10 +651,11 @@ dump: false
# Debug mode - you probably do not want this.
debug: false
+debug2: false
# Enable log - you probably do not want this.
log: false
# Please DO NOT change the following line manually!
# It is used by the automatic config updater.
-config-version: 44
+config-version: 45
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 049f191..0c94f64 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,6 +1,6 @@
main: de.jeff_media.ChestSort.ChestSortPlugin
name: ChestSort
-version: 9.1.1
+version: 9.3.0
api-version: "1.13"
description: Allows automatic chest sorting
author: mfnalex