9.6.0 release

This commit is contained in:
mfnalex 2021-04-14 20:16:27 +02:00
parent d035f540bc
commit 04eaebc552
5 changed files with 636 additions and 608 deletions

View File

@ -1,5 +1,8 @@
# Changelog # Changelog
## 9.5.2
- PlayerData is stored as NBT data instead of using separate files in 1.14.4 and later
## 9.5.1 ## 9.5.1
- Fixed version in plugin.yml - Fixed version in plugin.yml

View File

@ -10,7 +10,7 @@ https://www.spigotmc.org/resources/1-13-chestsort.59773/
If you want to use ChestSort as dependency for your own plugin, you can use our public maven repository. More information can be found in the [API documentation](https://github.com/JEFF-Media-GbR/Spigot-ChestSort/blob/master/HOW_TO_USE_API.md). If you want to use ChestSort as dependency for your own plugin, you can use our public maven repository. More information can be found in the [API documentation](https://github.com/JEFF-Media-GbR/Spigot-ChestSort/blob/master/HOW_TO_USE_API.md).
## Building .jar file ## Building .jar file
To build the .jar file, you will need maven. Also, the CrackShot library is in no public repository, so please create a directory called `lib` and put the latest CrackShot.jar file [(available here)](https://www.spigotmc.org/resources/crackshot-guns.48301/) inside it. Now you can do `mvn install` ~~To build the .jar file, you will need maven. Also, the CrackShot library is in no public repository, so please create a directory called `lib` and put the latest CrackShot.jar file [(available here)](https://www.spigotmc.org/resources/crackshot-guns.48301/) inside it.~~ (Not required as of ChestSort 9.6.0+)
## API ## API
If you want to use ChestSort's advanced sorting features for your own plugin, you can use the ChestSort API. It provides methods to sort any given inventory, following the rules you have specified in your ChestSort's plugin.yml and the corresponding category files. If you want to use ChestSort's advanced sorting features for your own plugin, you can use the ChestSort API. It provides methods to sort any given inventory, following the rules you have specified in your ChestSort's plugin.yml and the corresponding category files.

31
pom.xml
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>Automatically sorts your chests!</description> <description>Automatically sorts your chests!</description>
<version>9.5.1</version> <version>9.6.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
@ -44,8 +44,12 @@
<configuration> <configuration>
<relocations> <relocations>
<relocation> <relocation>
<pattern>de.jeff_media.PluginUpdateChecker</pattern> <pattern>de.jeff_media.jefflib</pattern>
<shadedPattern>de.jeff_media.ChestSort</shadedPattern> <shadedPattern>de.jeff_media.ChestSort.jefflib</shadedPattern>
</relocation>
<relocation>
<pattern>de.jeff_media.updatechecker</pattern>
<shadedPattern>de.jeff_media.ChestSort.updatechecker</shadedPattern>
</relocation> </relocation>
<relocation> <relocation>
<pattern>org.bstats</pattern> <pattern>org.bstats</pattern>
@ -126,10 +130,16 @@
<version>2.10.6</version> <version>2.10.6</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>de.jeff_media</groupId>
<artifactId>JeffLib</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.16.1-R0.1-SNAPSHOT</version> <version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -145,11 +155,10 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.shampaggon.crackshot</groupId> <groupId>de.jeff_media.thirdparty</groupId>
<artifactId>CSUtility</artifactId> <artifactId>CrackShot</artifactId>
<version>0.98.9</version> <version>0.98.11</version>
<scope>system</scope> <scope>provided</scope>
<systemPath>${project.basedir}/lib/CrackShot.jar</systemPath>
</dependency> </dependency>
<dependency> <dependency>
<groupId>at.pcgamingfreaks</groupId> <groupId>at.pcgamingfreaks</groupId>
@ -165,8 +174,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>de.jeff_media</groupId> <groupId>de.jeff_media</groupId>
<artifactId>PluginUpdateChecker</artifactId> <artifactId>SpigotUpdateChecker</artifactId>
<version>1.3.1</version> <version>1.2.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -1,4 +1,3 @@
/* /*
ChestSort - maintained by mfnalex / JEFF Media GbR ( www.jeff-media.de ) ChestSort - maintained by mfnalex / JEFF Media GbR ( www.jeff-media.de )
@ -28,25 +27,17 @@
package de.jeff_media.ChestSort; package de.jeff_media.ChestSort;
import java.io.BufferedWriter; import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksPlugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import de.jeff_media.ChestSort.config.Config; import de.jeff_media.ChestSort.config.Config;
import de.jeff_media.ChestSort.hooks.EnderContainersHook; import de.jeff_media.ChestSort.hooks.EnderContainersHook;
import de.jeff_media.ChestSort.hooks.GenericGUIHook; import de.jeff_media.ChestSort.hooks.GenericGUIHook;
import de.jeff_media.ChestSort.hooks.PlayerVaultsHook; import de.jeff_media.ChestSort.hooks.PlayerVaultsHook;
import de.jeff_media.ChestSort.placeholders.ChestSortPlaceholders; import de.jeff_media.ChestSort.placeholders.ChestSortPlaceholders;
import de.jeff_media.PluginUpdateChecker.PluginUpdateChecker; import de.jeff_media.ChestSort.utils.Utils;
import de.jeff_media.jefflib.JeffLib;
import de.jeff_media.jefflib.NBTAPI;
import de.jeff_media.jefflib.VersionUtil;
import de.jeff_media.updatechecker.UpdateChecker;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -58,91 +49,39 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import at.pcgamingfreaks.Minepacks.Bukkit.API.MinepacksPlugin; import java.io.*;
import de.jeff_media.ChestSort.utils.Utils; import java.util.*;
public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSortAPI.ChestSort { public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSortAPI.ChestSort {
ChestSortLogger lgr; private static double updateCheckInterval = 4 * 60 * 60; // in seconds. We check on startup and every 4 hours
Map<String, ChestSortPlayerSetting> perPlayerSettings = new HashMap<>();
HashMap<UUID,Long> hotkeyCooldown;
ChestSortMessages messages;
ChestSortOrganizer organizer;
PluginUpdateChecker updateChecker;
ChestSortListener listener;
ChestSortSettingsGUI settingsGUI;
ChestSortPermissionsHandler permissionsHandler;
String sortingMethod;
ArrayList<String> disabledWorlds;
ChestSortAPIHandler api;
final int currentConfigVersion = 47; final int currentConfigVersion = 47;
boolean usingMatchingConfig = true;
protected boolean debug = false;
boolean verbose = true;
final boolean hotkeyGUI = true; final boolean hotkeyGUI = true;
public EnderContainersHook enderContainersHook;
public GenericGUIHook genericHook;
public boolean hookCrackShot = false; public boolean hookCrackShot = false;
public boolean hookInventoryPages = false; public boolean hookInventoryPages = false;
public boolean hookMinepacks = false; public boolean hookMinepacks = false;
public GenericGUIHook genericHook;
public PlayerVaultsHook playerVaultsHook; public PlayerVaultsHook playerVaultsHook;
public EnderContainersHook enderContainersHook; protected boolean debug = false;
ChestSortAPIHandler api;
private static long updateCheckInterval = 4*60*60; // in seconds. We check on startup and every 4 hours ArrayList<String> disabledWorlds;
HashMap<UUID, Long> hotkeyCooldown;
String mcVersion; // 1.13.2 = 1_13_R2 ChestSortLogger lgr;
ChestSortListener listener;
// 1.14.4 = 1_14_R1 // 1.14.4 = 1_14_R1
// 1.8.0 = 1_8_R1 // 1.8.0 = 1_8_R1
int mcMinorVersion; // 14 for 1.14, 13 for 1.13, ... int mcMinorVersion; // 14 for 1.14, 13 for 1.13, ...
String mcVersion; // 1.13.2 = 1_13_R2
@Override ChestSortMessages messages;
public ChestSortAPIHandler getAPI() { ChestSortOrganizer organizer;
return this.api; Map<String, ChestSortPlayerSetting> perPlayerSettings = new HashMap<>();
} ChestSortPermissionsHandler permissionsHandler;
ChestSortSettingsGUI settingsGUI;
// Public API method to sort any given inventory String sortingMethod;
@Deprecated UpdateChecker updateChecker;
@Override boolean usingMatchingConfig = true;
public void sortInventory(Inventory inv) { boolean verbose = true;
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
getLogger().warning(String.format("%s has performed a call to a deprecated ChestSort API method. This is NOT a ChestSort error.",stackTraceElements[2]));
api.sortInventory(inv);
}
// Public API method to sort any given inventory inbetween startSlot and endSlot
@Deprecated
@Override
public void sortInventory(Inventory inv, int startSlot, int endSlot) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
getLogger().warning(String.format("%s has performed a call to a deprecated ChestSort API method. This is NOT a ChestSort error.",stackTraceElements[2]));
api.sortInventory(inv, startSlot, endSlot);
}
// Public API method to check if player has automatic chest sorting enabled
@Deprecated
@Override
public boolean sortingEnabled(Player p) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
getLogger().warning(String.format("%s has performed a call to a deprecated ChestSort API method. This is NOT a ChestSort error.",stackTraceElements[2]));
return isSortingEnabled(p);
}
boolean isSortingEnabled(Player p) {
if (perPlayerSettings == null) {
perPlayerSettings = new HashMap<>();
}
listener.plugin.registerPlayerIfNeeded(p);
return perPlayerSettings.get(p.getUniqueId().toString()).sortingEnabled;
}
public void debug(String t) {
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 // Creates the default configuration file
// Also checks the config-version of an already existing file. If the existing // Also checks the config-version of an already existing file. If the existing
@ -190,45 +129,6 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
} }
private void setDefaultConfigValues() {
// If you use an old config file with missing options, the following default
// values will be used instead
// for every missing option.
// By default, sorting is disabled. Every player has to run /chestsort once
getConfig().addDefault("use-permissions", true);
getConfig().addDefault("allow-automatic-sorting",true);
getConfig().addDefault("allow-automatic-inventory-sorting",true);
getConfig().addDefault("sorting-enabled-by-default", false);
getConfig().addDefault("inv-sorting-enabled-by-default", false);
getConfig().addDefault("show-message-when-using-chest", true);
getConfig().addDefault("show-message-when-using-chest-and-sorting-is-enabled", false);
getConfig().addDefault("show-message-again-after-logout", true);
getConfig().addDefault("sorting-method", "{category},{itemsFirst},{name},{color}");
getConfig().addDefault("allow-player-inventory-sorting", false);
getConfig().addDefault("check-for-updates", "true");
getConfig().addDefault("check-interval", 4);
getConfig().addDefault("auto-generate-category-files", true);
getConfig().addDefault("sort-time", "close");
getConfig().addDefault("allow-sorting-hotkeys", true);
getConfig().addDefault("allow-additional-hotkeys", true);
getConfig().addDefault("sorting-hotkeys.middle-click", true);
getConfig().addDefault("sorting-hotkeys.shift-click", true);
getConfig().addDefault("sorting-hotkeys.double-click", true);
getConfig().addDefault("sorting-hotkeys.shift-right-click", true);
getConfig().addDefault("additional-hotkeys.left-click", false);
getConfig().addDefault("additional-hotkeys.right-click", false);
getConfig().addDefault("dump", false);
getConfig().addDefault("log", false);
getConfig().addDefault("hook-crackshot", true);
getConfig().addDefault("hook-crackshot-prefix", "crackshot_weapon");
getConfig().addDefault("hook-inventorypages", true);
getConfig().addDefault("hook-minepacks", true);
getConfig().addDefault("hook-generic",true);
getConfig().addDefault("verbose", true); // Prints some information in onEnable()
}
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");
@ -245,41 +145,36 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
} }
} }
private void showOldConfigWarning() { public void debug(String t) {
getLogger().warning("=============================================="); if (debug) getLogger().warning("[DEBUG] " + t);
getLogger().warning("You were using an old config file. ChestSort"); }
getLogger().warning("has updated the file to the newest version.");
getLogger().warning("Your changes have been kept."); public void debug2(String t) {
getLogger().warning("=============================================="); if (getConfig().getBoolean(Config.DEBUG2)) getLogger().warning("[DEBUG2] " + t);
}
// Dumps all Materials into a csv file with their current category
void dump() {
try {
File file = new File(getDataFolder() + File.separator + "dump.csv");
FileOutputStream fos;
fos = new FileOutputStream(file);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
for (Material mat : Material.values()) {
bw.write(mat.name() + "," + organizer.getCategoryLinePair(mat.name()).getCategoryName());
bw.newLine();
}
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
@Override @Override
public void onDisable() { public ChestSortAPIHandler getAPI() {
// We have to unregister every player to save their perPlayerSettings return this.api;
for (Player p : getServer().getOnlinePlayers()) {
unregisterPlayer(p);
permissionsHandler.removePermissions(p);
}
}
public ChestSortPlayerSetting getPlayerSetting(Player p) {
registerPlayerIfNeeded(p);
return perPlayerSettings.get(p.getUniqueId().toString());
}
@Override
public void onEnable() {
String tmpVersion = getServer().getClass().getPackage().getName();
mcVersion = tmpVersion.substring(tmpVersion.lastIndexOf('.') + 1);
tmpVersion = mcVersion.substring(mcVersion.indexOf("_")+1);
mcMinorVersion = Integer.parseInt(tmpVersion.substring(0,tmpVersion.indexOf("_")));
load(false);
if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null){
new ChestSortPlaceholders(this).register();
}
} }
private String getCategoryList() { private String getCategoryList() {
@ -295,6 +190,181 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
} }
public ChestSortPlayerSetting getPlayerSetting(Player p) {
registerPlayerIfNeeded(p);
return perPlayerSettings.get(p.getUniqueId().toString());
}
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;
}
boolean isSortingEnabled(Player p) {
if (perPlayerSettings == null) {
perPlayerSettings = new HashMap<>();
}
listener.plugin.registerPlayerIfNeeded(p);
return perPlayerSettings.get(p.getUniqueId().toString()).sortingEnabled;
}
void load(boolean reload) {
if (reload) {
unregisterAllPlayers();
reloadConfig();
if (updateChecker != null) {
updateChecker.stop();
}
}
createConfig();
debug = getConfig().getBoolean("debug");
HandlerList.unregisterAll(this);
if (debug) {
ChestSortDebugger debugger = new ChestSortDebugger(this);
getServer().getPluginManager().registerEvents(debugger, this);
}
hookCrackShot = getConfig().getBoolean("hook-crackshot")
&& Bukkit.getPluginManager().getPlugin("CrackShot") instanceof Plugin;
hookInventoryPages = getConfig().getBoolean("hook-inventorypages")
&& Bukkit.getPluginManager().getPlugin("InventoryPages") instanceof Plugin;
hookMinepacks = getConfig().getBoolean("hook-minepacks")
&& Bukkit.getPluginManager().getPlugin("Minepacks") instanceof MinepacksPlugin;
genericHook = new GenericGUIHook(this, getConfig().getBoolean("hook-generic"));
saveDefaultCategories();
verbose = getConfig().getBoolean("verbose");
lgr = new ChestSortLogger(this, getConfig().getBoolean("log"));
messages = new ChestSortMessages(this);
organizer = new ChestSortOrganizer(this);
settingsGUI = new ChestSortSettingsGUI(this);
try {
if (Class.forName("net.md_5.bungee.api.chat.BaseComponent") != null) {
updateChecker = UpdateChecker.init(this, "https://api.jeff-media.de/chestsort/chestsort-latest-version.txt")
.setChangelogLink("https://www.chestsort.de/changelog")
.setDonationLink("https://paypal.me/mfnalex")
.setDownloadLink("https://www.chestsort.de");
} 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 = getConfig().getDouble("check-interval");
sortingMethod = getConfig().getString("sorting-method");
playerVaultsHook = new PlayerVaultsHook(this);
enderContainersHook = new EnderContainersHook(this);
getServer().getPluginManager().registerEvents(listener, this);
getServer().getPluginManager().registerEvents(settingsGUI, this);
ChestSortChestSortCommand chestsortCommandExecutor = new ChestSortChestSortCommand(this);
ChestSortTabCompleter tabCompleter = new ChestSortTabCompleter();
this.getCommand("sort").setExecutor(chestsortCommandExecutor);
this.getCommand("sort").setTabCompleter(tabCompleter);
ChestSortInvSortCommand invsortCommandExecutor = new ChestSortInvSortCommand(this);
this.getCommand("invsort").setExecutor(invsortCommandExecutor);
this.getCommand("invsort").setTabCompleter(tabCompleter);
if (verbose) {
getLogger().info("Use permissions: " + getConfig().getBoolean("use-permissions"));
getLogger().info("Current sorting method: " + sortingMethod);
getLogger().info("Allow automatic chest sorting:" + getConfig().getBoolean("allow-automatic-sorting"));
getLogger().info(" |- Chest sorting enabled by default: " + getConfig().getBoolean("sorting-enabled-by-default"));
getLogger().info(" |- Sort time: " + getConfig().getString("sort-time"));
getLogger().info("Allow automatic inventory sorting:" + getConfig().getBoolean("allow-automatic-inventory-sorting"));
getLogger().info(" |- Inventory sorting enabled by default: " + getConfig().getBoolean("inv-sorting-enabled-by-default"));
getLogger().info("Auto generate category files: " + getConfig().getBoolean("auto-generate-category-files"));
getLogger().info("Allow hotkeys: " + getConfig().getBoolean("allow-sorting-hotkeys"));
if (getConfig().getBoolean("allow-sorting-hotkeys")) {
getLogger().info("Hotkeys enabled by default:");
getLogger().info(" |- Middle-Click: " + getConfig().getBoolean("sorting-hotkeys.middle-click"));
getLogger().info(" |- Shift-Click: " + getConfig().getBoolean("sorting-hotkeys.shift-click"));
getLogger().info(" |- Double-Click: " + getConfig().getBoolean("sorting-hotkeys.double-click"));
getLogger().info(" |- Shift-Right-Click: " + getConfig().getBoolean("sorting-hotkeys.shift-right-click"));
}
getLogger().info("Allow additional hotkeys: " + getConfig().getBoolean("allow-additional-hotkeys"));
if (getConfig().getBoolean("allow-additional-hotkeys")) {
getLogger().info("Additional hotkeys enabled by default:");
getLogger().info(" |- Left-Click: " + getConfig().getBoolean("additional-hotkeys.left-click"));
getLogger().info(" |- Right-Click: " + getConfig().getBoolean("additional-hotkeys.right-click"));
}
getLogger().info("Check for updates: " + getConfig().getString("check-for-updates"));
if (getConfig().getString("check-for-updates").equalsIgnoreCase("true")) {
getLogger().info("Check interval: " + getConfig().getString("check-interval") + " hours (" + updateCheckInterval + " seconds)");
}
getLogger().info("Categories: " + getCategoryList());
}
if (updateChecker != null) {
if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("true")) {
updateChecker.checkEveryXHours(updateCheckInterval).checkNow();
} // When set to on-startup, we check right now (delay 0)
else if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("on-startup")) {
updateChecker.checkNow();
}
}
registerMetrics();
if (getConfig().getBoolean("dump")) {
dump();
}
for (Player p : getServer().getOnlinePlayers()) {
permissionsHandler.addPermissions(p);
}
// End Reload
}
@Override
public void onDisable() {
// We have to unregister every player to save their perPlayerSettings
for (Player p : getServer().getOnlinePlayers()) {
unregisterPlayer(p);
permissionsHandler.removePermissions(p);
}
}
@Override
public void onEnable() {
JeffLib.init(this);
String tmpVersion = getServer().getClass().getPackage().getName();
mcVersion = tmpVersion.substring(tmpVersion.lastIndexOf('.') + 1);
tmpVersion = mcVersion.substring(mcVersion.indexOf("_") + 1);
mcMinorVersion = Integer.parseInt(tmpVersion.substring(0, tmpVersion.indexOf("_")));
load(false);
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
new ChestSortPlaceholders(this).register();
}
}
private void registerMetrics() { private void registerMetrics() {
// Metrics will need json-simple with 1.14 API. // Metrics will need json-simple with 1.14 API.
Metrics bStats = new Metrics(this, 3089); Metrics bStats = new Metrics(this, 3089);
@ -305,7 +375,7 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
bStats.addCustomChart( bStats.addCustomChart(
new Metrics.SimplePie("check_for_updates", ()->getConfig().getString("check-for-updates", "true"))); new Metrics.SimplePie("check_for_updates", ()->getConfig().getString("check-for-updates", "true")));
bStats.addCustomChart( bStats.addCustomChart(
new Metrics.SimplePie("update_interval", () -> Long.toString(updateCheckInterval))); new Metrics.SimplePie("update_interval", ()->Double.toString(updateCheckInterval)));
bStats.addCustomChart(new Metrics.SimplePie("allow_automatic_sorting", bStats.addCustomChart(new Metrics.SimplePie("allow_automatic_sorting",
()->Boolean.toString(getConfig().getBoolean("allow-automatic-sorting")))); ()->Boolean.toString(getConfig().getBoolean("allow-automatic-sorting"))));
@ -348,6 +418,86 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
} }
void registerPlayerIfNeeded(Player p) {
// Players are stored by their UUID, so that name changes don't break player's
// settings
UUID uniqueId = p.getUniqueId();
// Add player to map only if they aren't registered already
if (!perPlayerSettings.containsKey(uniqueId.toString())) {
// Player settings are stored in a file named after the player's UUID
File playerFile = new File(getDataFolder() + File.separator + "playerdata",
p.getUniqueId().toString() + ".yml");
YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(playerFile);
playerConfig.addDefault("invSortingEnabled", getConfig().getBoolean("inv-sorting-enabled-by-default"));
playerConfig.addDefault("middleClick", getConfig().getBoolean("sorting-hotkeys.middle-click"));
playerConfig.addDefault("shiftClick", getConfig().getBoolean("sorting-hotkeys.shift-click"));
playerConfig.addDefault("doubleClick", getConfig().getBoolean("sorting-hotkeys.double-click"));
playerConfig.addDefault("shiftRightClick", getConfig().getBoolean("sorting-hotkeys.shift-right-click"));
playerConfig.addDefault("leftClick", getConfig().getBoolean("additional-hotkeys.left-click"));
playerConfig.addDefault("rightClick", getConfig().getBoolean("additional-hotkeys.right-click"));
boolean activeForThisPlayer;
boolean invActiveForThisPlayer;
boolean middleClick;
boolean shiftClick;
boolean doubleClick;
boolean shiftRightClick;
boolean leftClick;
boolean rightClick;
boolean changed = false;
if (!playerFile.exists()) {
// If the player settings file does not exist for this player, set it to the
// default value
activeForThisPlayer = getConfig().getBoolean("sorting-enabled-by-default");
invActiveForThisPlayer = getConfig().getBoolean("inv-sorting-enabled-by-default");
middleClick = getConfig().getBoolean("sorting-hotkeys.middle-click");
shiftClick = getConfig().getBoolean("sorting-hotkeys.shift-click");
doubleClick = getConfig().getBoolean("sorting-hotkeys.double-click");
shiftRightClick = getConfig().getBoolean("sorting-hotkeys.shift-right-click");
leftClick = getConfig().getBoolean("additional-hotkeys.left-click");
rightClick = getConfig().getBoolean("additional-hotkeys.right-click");
if (debug) {
getLogger().info("Player " + p.getName() + " does not have player settings yet, using default values.");
}
// Because this is new a file, we have to save it on shutdown/disconnect
changed = true;
} else {
// If the file exists, check if the player has sorting enabled
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")))));
playerFile.delete();
}
ChestSortPlayerSetting newSettings = new ChestSortPlayerSetting(activeForThisPlayer, invActiveForThisPlayer, middleClick, shiftClick, doubleClick, shiftRightClick, leftClick, rightClick, changed);
// when "show-message-again-after-logout" is enabled, we don't care if the
// player already saw the message
if (!getConfig().getBoolean("show-message-again-after-logout")) {
if(VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01) && !playerFile.exists()) {
NBTAPI.getNBT(p,"hasSeenMessage", String.valueOf(false));
} else {
newSettings.hasSeenMessage = playerConfig.getBoolean("hasSeenMessage");
}
}
// Finally add the PlayerSetting object to the map
perPlayerSettings.put(uniqueId.toString(), newSettings);
}
}
// Saves default category files, when enabled in the config // Saves default category files, when enabled in the config
private void saveDefaultCategories() { private void saveDefaultCategories() {
@ -423,6 +573,94 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
} }
} }
private void setDefaultConfigValues() {
// If you use an old config file with missing options, the following default
// values will be used instead
// for every missing option.
// By default, sorting is disabled. Every player has to run /chestsort once
getConfig().addDefault("use-permissions", true);
getConfig().addDefault("allow-automatic-sorting", true);
getConfig().addDefault("allow-automatic-inventory-sorting", true);
getConfig().addDefault("sorting-enabled-by-default", false);
getConfig().addDefault("inv-sorting-enabled-by-default", false);
getConfig().addDefault("show-message-when-using-chest", true);
getConfig().addDefault("show-message-when-using-chest-and-sorting-is-enabled", false);
getConfig().addDefault("show-message-again-after-logout", true);
getConfig().addDefault("sorting-method", "{category},{itemsFirst},{name},{color}");
getConfig().addDefault("allow-player-inventory-sorting", false);
getConfig().addDefault("check-for-updates", "true");
getConfig().addDefault("check-interval", 4);
getConfig().addDefault("auto-generate-category-files", true);
getConfig().addDefault("sort-time", "close");
getConfig().addDefault("allow-sorting-hotkeys", true);
getConfig().addDefault("allow-additional-hotkeys", true);
getConfig().addDefault("sorting-hotkeys.middle-click", true);
getConfig().addDefault("sorting-hotkeys.shift-click", true);
getConfig().addDefault("sorting-hotkeys.double-click", true);
getConfig().addDefault("sorting-hotkeys.shift-right-click", true);
getConfig().addDefault("additional-hotkeys.left-click", false);
getConfig().addDefault("additional-hotkeys.right-click", false);
getConfig().addDefault("dump", false);
getConfig().addDefault("log", false);
getConfig().addDefault("hook-crackshot", true);
getConfig().addDefault("hook-crackshot-prefix", "crackshot_weapon");
getConfig().addDefault("hook-inventorypages", true);
getConfig().addDefault("hook-minepacks", true);
getConfig().addDefault("hook-generic", true);
getConfig().addDefault("verbose", true); // Prints some information in onEnable()
}
private void showOldConfigWarning() {
getLogger().warning("==============================================");
getLogger().warning("You were using an old config file. ChestSort");
getLogger().warning("has updated the file to the newest version.");
getLogger().warning("Your changes have been kept.");
getLogger().warning("==============================================");
}
// Public API method to sort any given inventory
@Deprecated
@Override
public void sortInventory(Inventory inv) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
getLogger().warning(String.format("%s has performed a call to a deprecated ChestSort API method. This is NOT a ChestSort error.", stackTraceElements[2]));
api.sortInventory(inv);
}
// Public API method to sort any given inventory inbetween startSlot and endSlot
@Deprecated
@Override
public void sortInventory(Inventory inv, int startSlot, int endSlot) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
getLogger().warning(String.format("%s has performed a call to a deprecated ChestSort API method. This is NOT a ChestSort error.", stackTraceElements[2]));
api.sortInventory(inv, startSlot, endSlot);
}
// Public API method to check if player has automatic chest sorting enabled
@Deprecated
@Override
public boolean sortingEnabled(Player p) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
getLogger().warning(String.format("%s has performed a call to a deprecated ChestSort API method. This is NOT a ChestSort error.", stackTraceElements[2]));
return isSortingEnabled(p);
}
void unregisterAllPlayers() {
if (perPlayerSettings != null && perPlayerSettings.size() > 0) {
Iterator<String> it = perPlayerSettings.keySet().iterator();
while (it.hasNext()) {
Player p = getServer().getPlayer(it.next());
if (p != null) {
unregisterPlayer(p);
}
}
} else {
perPlayerSettings = new HashMap<>();
}
}
// Unregister a player and save their settings in the playerdata folder // Unregister a player and save their settings in the playerdata folder
void unregisterPlayer(Player p) { void unregisterPlayer(Player p) {
// File will be named by the player's uuid. This will prevent problems on player // File will be named by the player's uuid. This will prevent problems on player
@ -435,6 +673,18 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
if (perPlayerSettings.containsKey(uniqueId.toString())) { if (perPlayerSettings.containsKey(uniqueId.toString())) {
ChestSortPlayerSetting setting = perPlayerSettings.get(p.getUniqueId().toString()); ChestSortPlayerSetting setting = perPlayerSettings.get(p.getUniqueId().toString());
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_14_4_R01)) {
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));
} else {
File playerFile = new File(getDataFolder() + File.separator + "playerdata", File playerFile = new File(getDataFolder() + File.separator + "playerdata",
p.getUniqueId().toString() + ".yml"); p.getUniqueId().toString() + ".yml");
YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(playerFile); YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(playerFile);
@ -459,244 +709,10 @@ public class ChestSortPlugin extends JavaPlugin implements de.jeff_media.ChestSo
e.printStackTrace(); e.printStackTrace();
} }
}
perPlayerSettings.remove(uniqueId.toString()); perPlayerSettings.remove(uniqueId.toString());
} }
} }
void load(boolean reload) {
if(reload) {
unregisterAllPlayers();
reloadConfig();
if(updateChecker != null) {
updateChecker.stop();
}
}
createConfig();
debug = getConfig().getBoolean("debug");
HandlerList.unregisterAll(this);
if(debug) {
ChestSortDebugger debugger = new ChestSortDebugger(this);
getServer().getPluginManager().registerEvents(debugger, this);
}
hookCrackShot = getConfig().getBoolean("hook-crackshot")
&& Bukkit.getPluginManager().getPlugin("CrackShot") instanceof Plugin;
hookInventoryPages = getConfig().getBoolean("hook-inventorypages")
&& Bukkit.getPluginManager().getPlugin("InventoryPages") instanceof Plugin;
hookMinepacks = getConfig().getBoolean("hook-minepacks")
&& Bukkit.getPluginManager().getPlugin("Minepacks") instanceof MinepacksPlugin;
genericHook = new GenericGUIHook(this,getConfig().getBoolean("hook-generic"));
saveDefaultCategories();
verbose = getConfig().getBoolean("verbose");
lgr = new ChestSortLogger(this,getConfig().getBoolean("log"));
messages = new ChestSortMessages(this);
organizer = new ChestSortOrganizer(this);
settingsGUI = new ChestSortSettingsGUI(this);
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);
enderContainersHook = new EnderContainersHook(this);
getServer().getPluginManager().registerEvents(listener, this);
getServer().getPluginManager().registerEvents(settingsGUI, this);
ChestSortChestSortCommand chestsortCommandExecutor = new ChestSortChestSortCommand(this);
ChestSortTabCompleter tabCompleter = new ChestSortTabCompleter();
this.getCommand("sort").setExecutor(chestsortCommandExecutor);
this.getCommand("sort").setTabCompleter(tabCompleter);
ChestSortInvSortCommand invsortCommandExecutor = new ChestSortInvSortCommand(this);
this.getCommand("invsort").setExecutor(invsortCommandExecutor);
this.getCommand("invsort").setTabCompleter(tabCompleter);
if (verbose) {
getLogger().info("Use permissions: " + getConfig().getBoolean("use-permissions"));
getLogger().info("Current sorting method: " + sortingMethod);
getLogger().info("Allow automatic chest sorting:" + getConfig().getBoolean("allow-automatic-sorting"));
getLogger().info(" |- Chest sorting enabled by default: " + getConfig().getBoolean("sorting-enabled-by-default"));
getLogger().info(" |- Sort time: " + getConfig().getString("sort-time"));
getLogger().info("Allow automatic inventory sorting:" + getConfig().getBoolean("allow-automatic-inventory-sorting"));
getLogger().info(" |- Inventory sorting enabled by default: " + getConfig().getBoolean("inv-sorting-enabled-by-default"));
getLogger().info("Auto generate category files: " + getConfig().getBoolean("auto-generate-category-files"));
getLogger().info("Allow hotkeys: " + getConfig().getBoolean("allow-sorting-hotkeys"));
if(getConfig().getBoolean("allow-sorting-hotkeys")) {
getLogger().info("Hotkeys enabled by default:");
getLogger().info(" |- Middle-Click: " + getConfig().getBoolean("sorting-hotkeys.middle-click"));
getLogger().info(" |- Shift-Click: " + getConfig().getBoolean("sorting-hotkeys.shift-click"));
getLogger().info(" |- Double-Click: " + getConfig().getBoolean("sorting-hotkeys.double-click"));
getLogger().info(" |- Shift-Right-Click: " + getConfig().getBoolean("sorting-hotkeys.shift-right-click"));
}
getLogger().info("Allow additional hotkeys: " + getConfig().getBoolean("allow-additional-hotkeys"));
if(getConfig().getBoolean("allow-additional-hotkeys")) {
getLogger().info("Additional hotkeys enabled by default:");
getLogger().info(" |- Left-Click: " + getConfig().getBoolean("additional-hotkeys.left-click"));
getLogger().info(" |- Right-Click: " + getConfig().getBoolean("additional-hotkeys.right-click"));
}
getLogger().info("Check for updates: " + getConfig().getString("check-for-updates"));
if(getConfig().getString("check-for-updates").equalsIgnoreCase("true")) {
getLogger().info("Check interval: " + getConfig().getString("check-interval") + " hours ("+updateCheckInterval+" seconds)");
}
getLogger().info("Categories: " + getCategoryList());
}
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();
if(getConfig().getBoolean("dump")) {
dump();
}
for(Player p : getServer().getOnlinePlayers()) {
permissionsHandler.addPermissions(p);
}
// End Reload
}
void unregisterAllPlayers() {
if(perPlayerSettings!=null && perPlayerSettings.size()>0) {
Iterator<String> it = perPlayerSettings.keySet().iterator();
while(it.hasNext()) {
Player p = getServer().getPlayer(it.next());
if(p != null) {
unregisterPlayer(p);
}
}
} else {
perPlayerSettings = new HashMap<>();
}
}
// Dumps all Materials into a csv file with their current category
void dump() {
try {
File file = new File(getDataFolder() + File.separator + "dump.csv");
FileOutputStream fos;
fos = new FileOutputStream(file);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
for(Material mat : Material.values()) {
bw.write(mat.name()+","+organizer.getCategoryLinePair(mat.name()).getCategoryName());
bw.newLine();
}
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
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
UUID uniqueId = p.getUniqueId();
// Add player to map only if they aren't registered already
if (!perPlayerSettings.containsKey(uniqueId.toString())) {
// Player settings are stored in a file named after the player's UUID
File playerFile = new File(getDataFolder() + File.separator + "playerdata",
p.getUniqueId().toString() + ".yml");
YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(playerFile);
playerConfig.addDefault("invSortingEnabled", getConfig().getBoolean("inv-sorting-enabled-by-default"));
playerConfig.addDefault("middleClick", getConfig().getBoolean("sorting-hotkeys.middle-click"));
playerConfig.addDefault("shiftClick", getConfig().getBoolean("sorting-hotkeys.shift-click"));
playerConfig.addDefault("doubleClick", getConfig().getBoolean("sorting-hotkeys.double-click"));
playerConfig.addDefault("shiftRightClick", getConfig().getBoolean("sorting-hotkeys.shift-right-click"));
playerConfig.addDefault("leftClick", getConfig().getBoolean("additional-hotkeys.left-click"));
playerConfig.addDefault("rightClick", getConfig().getBoolean("additional-hotkeys.right-click"));
boolean activeForThisPlayer;
boolean invActiveForThisPlayer;
boolean middleClick, shiftClick, doubleClick, shiftRightClick, leftClick, rightClick;
boolean changed = false;
if (!playerFile.exists()) {
// If the player settings file does not exist for this player, set it to the
// default value
activeForThisPlayer = getConfig().getBoolean("sorting-enabled-by-default");
invActiveForThisPlayer = getConfig().getBoolean("inv-sorting-enabled-by-default");
middleClick = getConfig().getBoolean("sorting-hotkeys.middle-click");
shiftClick = getConfig().getBoolean("sorting-hotkeys.shift-click");
doubleClick = getConfig().getBoolean("sorting-hotkeys.double-click");
shiftRightClick = getConfig().getBoolean("sorting-hotkeys.shift-right-click");
leftClick = getConfig().getBoolean("additional-hotkeys.left-click");
rightClick = getConfig().getBoolean("additional-hotkeys.right-click");
if(debug) {
getLogger().info("Player "+p.getName()+" does not have player settings yet, using default values.");
}
// Because this is new a file, we have to save it on shutdown/disconnect
changed=true;
} else {
// If the file exists, check if the player has sorting enabled
activeForThisPlayer = playerConfig.getBoolean("sortingEnabled");
invActiveForThisPlayer = playerConfig.getBoolean("invSortingEnabled",getConfig().getBoolean("inv-sorting-enabled-by-default"));
middleClick = playerConfig.getBoolean("middleClick");
shiftClick = playerConfig.getBoolean("shiftClick");
doubleClick = playerConfig.getBoolean("doubleClick");
shiftRightClick = playerConfig.getBoolean("shiftRightClick");
leftClick = playerConfig.getBoolean("leftClick",getConfig().getBoolean("additional-hotkeys.left-click"));
rightClick = playerConfig.getBoolean("rightClick",getConfig().getBoolean("additional-hotkeys.right-click"));
}
ChestSortPlayerSetting newSettings = new ChestSortPlayerSetting(activeForThisPlayer,invActiveForThisPlayer,middleClick,shiftClick,doubleClick,shiftRightClick,leftClick,rightClick,changed);
// when "show-message-again-after-logout" is enabled, we don't care if the
// player already saw the message
if (!getConfig().getBoolean("show-message-again-after-logout")) {
newSettings.hasSeenMessage = playerConfig.getBoolean("hasSeenMessage");
}
// Finally add the PlayerSetting object to the map
perPlayerSettings.put(uniqueId.toString(), newSettings);
}
}
} }

View File

@ -1,6 +1,6 @@
main: de.jeff_media.ChestSort.ChestSortPlugin main: de.jeff_media.ChestSort.ChestSortPlugin
name: ChestSort name: ChestSort
version: 9.5.1 version: 9.6.0
api-version: "1.13" api-version: "1.13"
description: Allows automatic chest sorting description: Allows automatic chest sorting
author: mfnalex author: mfnalex