mirror of
https://github.com/JEFF-Media-GbR/ChestSort.git
synced 2024-09-27 14:42:34 +02:00
7.7-pre1
This commit is contained in:
parent
d177ee6c6b
commit
7131dc6130
@ -1,5 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
## 7.7-pre1
|
||||
- Moved /invsort command to separate class
|
||||
- Moved registerPlayerIfNeeded from Listener to main class
|
||||
- Save player configs only if they have changed
|
||||
|
||||
## 7.6.1
|
||||
- Changed description for hotkeys in config.yml
|
||||
- Updated French translation
|
||||
|
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>de.jeffclan</groupId>
|
||||
<artifactId>JeffChestSort</artifactId>
|
||||
<version>7.6.1</version>
|
||||
<version>7.7-pre1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>JeffChestSort</name>
|
||||
|
@ -0,0 +1,92 @@
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import de.jeffclan.JeffChestSort.JeffChestSortPlayerSetting;
|
||||
import de.jeffclan.JeffChestSort.JeffChestSortPlugin;
|
||||
|
||||
public class JeffChestSortChestSortCommand implements CommandExecutor {
|
||||
|
||||
JeffChestSortPlugin plugin;
|
||||
|
||||
JeffChestSortChestSortCommand(JeffChestSortPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
// This command toggles automatic chest sorting for the player that runs the command
|
||||
if (!command.getName().equalsIgnoreCase("chestsort")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
|
||||
if(args.length!=0) {
|
||||
if(args[0].equalsIgnoreCase("debug")) {
|
||||
plugin.debug=true;
|
||||
plugin.getLogger().info("ChestSort debug mode enabled.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(plugin.messages.MSG_PLAYERSONLY);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) sender;
|
||||
|
||||
// fix for Spigot's stupid /reload function
|
||||
plugin.registerPlayerIfNeeded(p);
|
||||
|
||||
// Settings GUI
|
||||
if(args.length>0) {
|
||||
if(args[0].equalsIgnoreCase("hotkey") || args[0].equalsIgnoreCase("hotkeys")) {
|
||||
|
||||
// if(plugin.hotkeyGUI==false) {
|
||||
// p.sendMessage(plugin.messages.MSG_ERR_HOTKEYSDISABLED);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
// Settings GUI End
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
if(args.length>0
|
||||
&& !args[0].equalsIgnoreCase("toggle")
|
||||
&& !args[0].equalsIgnoreCase("on")
|
||||
&& !args[0].equalsIgnoreCase("off")) {
|
||||
p.sendMessage(String.format(plugin.messages.MSG_INVALIDOPTIONS,"\""+args[0]+"\"","\"toggle\", \"on\", \"off\", \"hotkeys\""));
|
||||
return true;
|
||||
}
|
||||
if(args.length==0 || args[0].equalsIgnoreCase("toggle")) {
|
||||
setting.toggleChestSorting();
|
||||
}
|
||||
else if(args[0].equalsIgnoreCase("on")) {
|
||||
setting.enableChestSorting();
|
||||
}
|
||||
else if(args[0].equalsIgnoreCase("off")) {
|
||||
setting.disableChestSorting();
|
||||
}
|
||||
setting.hasSeenMessage=true;
|
||||
|
||||
if (setting.sortingEnabled) {
|
||||
p.sendMessage(plugin.messages.MSG_ACTIVATED);
|
||||
} else {
|
||||
p.sendMessage(plugin.messages.MSG_DEACTIVATED);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class JeffChestSortCommandExecutor implements CommandExecutor {
|
||||
|
||||
JeffChestSortPlugin plugin;
|
||||
|
||||
JeffChestSortCommandExecutor(JeffChestSortPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
// This command toggles automatic chest sorting for the player that runs the command
|
||||
if (command.getName().equalsIgnoreCase("chestsort")) {
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
|
||||
if(args.length!=0) {
|
||||
if(args[0].equalsIgnoreCase("debug")) {
|
||||
plugin.debug=true;
|
||||
sender.sendMessage("ChestSort debug mode enabled.");
|
||||
return true;
|
||||
} else if(args[0].equalsIgnoreCase("reload")) {
|
||||
// TODO: EXPERIMENTAL
|
||||
plugin.onDisable();
|
||||
plugin.onEnable();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(plugin.messages.MSG_PLAYERSONLY);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) sender;
|
||||
|
||||
// fix for Spigot's stupid /reload function
|
||||
plugin.listener.registerPlayerIfNeeded(p);
|
||||
|
||||
// Settings GUI
|
||||
if(args.length>0) {
|
||||
if(args[0].equalsIgnoreCase("hotkey") || args[0].equalsIgnoreCase("hotkeys")) {
|
||||
|
||||
// if(plugin.hotkeyGUI==false) {
|
||||
// p.sendMessage(plugin.messages.MSG_ERR_HOTKEYSDISABLED);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
// Settings GUI End
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
if(args.length>0
|
||||
&& !args[0].equalsIgnoreCase("toggle")
|
||||
&& !args[0].equalsIgnoreCase("on")
|
||||
&& !args[0].equalsIgnoreCase("off")) {
|
||||
p.sendMessage(String.format(plugin.messages.MSG_INVALIDOPTIONS,"\""+args[0]+"\"","\"toggle\", \"on\", \"off\", \"hotkeys\""));
|
||||
return true;
|
||||
}
|
||||
if(args.length==0 || args[0].equalsIgnoreCase("toggle")) {
|
||||
setting.sortingEnabled = !setting.sortingEnabled;
|
||||
}
|
||||
else if(args[0].equalsIgnoreCase("on")) {
|
||||
setting.sortingEnabled = true;
|
||||
}
|
||||
else if(args[0].equalsIgnoreCase("off")) {
|
||||
setting.sortingEnabled = false;
|
||||
}
|
||||
setting.hasSeenMessage=true;
|
||||
|
||||
if (setting.sortingEnabled) {
|
||||
p.sendMessage(plugin.messages.MSG_ACTIVATED);
|
||||
} else {
|
||||
p.sendMessage(plugin.messages.MSG_DEACTIVATED);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if(command.getName().equalsIgnoreCase("invsort")) {
|
||||
// This command sorts the player's inventory
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.messages.MSG_PLAYERSONLY);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) sender;
|
||||
|
||||
int start = 9;
|
||||
int end = 35;
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
if(args.length>0) {
|
||||
if(args[0].equalsIgnoreCase("all")) {
|
||||
start=0;
|
||||
end=35;
|
||||
} else if(args[0].equalsIgnoreCase("hotbar")) {
|
||||
start=0;
|
||||
end=8;
|
||||
} else if(args[0].equalsIgnoreCase("inv")) {
|
||||
start=9;
|
||||
end=35;
|
||||
} else if(args[0].equalsIgnoreCase("on")) {
|
||||
setting.invSortingEnabled = true;
|
||||
p.sendMessage(plugin.messages.MSG_INVACTIVATED);
|
||||
return true;
|
||||
} else if(args[0].equalsIgnoreCase("off")) {
|
||||
setting.invSortingEnabled = false;
|
||||
p.sendMessage(plugin.messages.MSG_INVDEACTIVATED);
|
||||
return true;
|
||||
} else if(args[0].equalsIgnoreCase("toggle")) {
|
||||
setting.invSortingEnabled = !setting.invSortingEnabled;
|
||||
if(setting.invSortingEnabled) {
|
||||
p.sendMessage(plugin.messages.MSG_INVACTIVATED);
|
||||
} else {
|
||||
p.sendMessage(plugin.messages.MSG_INVDEACTIVATED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
p.sendMessage(String.format(plugin.messages.MSG_INVALIDOPTIONS,"\""+args[0]+"\"","\"on\", \"off\", \"toggle\", \"inv\", \"hotbar\", \"all\""));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.sortInventory(p.getInventory(), start, end);
|
||||
p.sendMessage(plugin.messages.MSG_PLAYERINVSORTED);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class JeffChestSortInvSortCommand implements CommandExecutor {
|
||||
|
||||
JeffChestSortPlugin plugin;
|
||||
|
||||
JeffChestSortInvSortCommand(JeffChestSortPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
// This command toggles automatic chest sorting for the player that runs the command
|
||||
if (!command.getName().equalsIgnoreCase("invsort")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.messages.MSG_PLAYERSONLY);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) sender;
|
||||
|
||||
int start = 9;
|
||||
int end = 35;
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
if(args.length>0) {
|
||||
if(args[0].equalsIgnoreCase("all")) {
|
||||
start=0;
|
||||
end=35;
|
||||
} else if(args[0].equalsIgnoreCase("hotbar")) {
|
||||
start=0;
|
||||
end=8;
|
||||
} else if(args[0].equalsIgnoreCase("inv")) {
|
||||
start=9;
|
||||
end=35;
|
||||
} else if(args[0].equalsIgnoreCase("on")) {
|
||||
setting.enableInvSorting();
|
||||
p.sendMessage(plugin.messages.MSG_INVACTIVATED);
|
||||
return true;
|
||||
} else if(args[0].equalsIgnoreCase("off")) {
|
||||
setting.disableInvSorting();
|
||||
p.sendMessage(plugin.messages.MSG_INVDEACTIVATED);
|
||||
return true;
|
||||
} else if(args[0].equalsIgnoreCase("toggle")) {
|
||||
setting.toggleInvSorting();
|
||||
if(setting.invSortingEnabled) {
|
||||
p.sendMessage(plugin.messages.MSG_INVACTIVATED);
|
||||
} else {
|
||||
p.sendMessage(plugin.messages.MSG_INVDEACTIVATED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
p.sendMessage(String.format(plugin.messages.MSG_INVALIDOPTIONS,"\""+args[0]+"\"","\"on\", \"off\", \"toggle\", \"inv\", \"hotbar\", \"all\""));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.sortInventory(p.getInventory(), start, end);
|
||||
p.sendMessage(plugin.messages.MSG_PLAYERINVSORTED);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +1,9 @@
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.DoubleChest;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -38,11 +34,6 @@ public class JeffChestSortListener implements Listener {
|
||||
|
||||
// DEBUG
|
||||
// To enable debug mode, put debug: true into your config.yml
|
||||
// Checking for my username because I always forget to comment this out before
|
||||
// releases
|
||||
// if (event.getPlayer().getName().equalsIgnoreCase("mfnalex")) {
|
||||
// plugin.debug = true;
|
||||
// }
|
||||
|
||||
// OPs will get an update notice if a new update is available
|
||||
if (event.getPlayer().isOp()) {
|
||||
@ -50,67 +41,10 @@ public class JeffChestSortListener implements Listener {
|
||||
}
|
||||
|
||||
// Put player into our perPlayerSettings map
|
||||
registerPlayerIfNeeded(event.getPlayer());
|
||||
plugin.registerPlayerIfNeeded(event.getPlayer());
|
||||
|
||||
}
|
||||
|
||||
// Put player into our perPlayerSettings map
|
||||
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 (!plugin.PerPlayerSettings.containsKey(uniqueId.toString())) {
|
||||
|
||||
// Player settings are stored in a file named after the player's UUID
|
||||
File playerFile = new File(plugin.getDataFolder() + File.separator + "playerdata",
|
||||
p.getUniqueId().toString() + ".yml");
|
||||
YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(playerFile);
|
||||
|
||||
playerConfig.addDefault("invSortingEnabled", plugin.getConfig().getBoolean("inv-sorting-enabled-by-default"));
|
||||
playerConfig.addDefault("middleClick", plugin.getConfig().getBoolean("hotkeys.middle-click"));
|
||||
playerConfig.addDefault("shiftClick", plugin.getConfig().getBoolean("hotkeys.shift-click"));
|
||||
playerConfig.addDefault("doubleClick", plugin.getConfig().getBoolean("hotkeys.double-click"));
|
||||
playerConfig.addDefault("shiftRightClick", plugin.getConfig().getBoolean("hotkeys.shift-right-click"));
|
||||
|
||||
boolean activeForThisPlayer = false;
|
||||
boolean invActiveForThisPlayer = false;
|
||||
boolean middleClick, shiftClick, doubleClick, shiftRightClick;
|
||||
|
||||
if (!playerFile.exists()) {
|
||||
// If the player settings file does not exist for this player, set it to the
|
||||
// default value
|
||||
activeForThisPlayer = plugin.getConfig().getBoolean("sorting-enabled-by-default");
|
||||
invActiveForThisPlayer = plugin.getConfig().getBoolean("inv-sorting-enabled-by-default");
|
||||
middleClick = plugin.getConfig().getBoolean("hotkeys.middle-click");
|
||||
shiftClick = plugin.getConfig().getBoolean("hotkeys.shift-click");
|
||||
doubleClick = plugin.getConfig().getBoolean("hotkeys.double-click");
|
||||
shiftRightClick = plugin.getConfig().getBoolean("hotkeys.shift-right-click");
|
||||
} else {
|
||||
// If the file exists, check if the player has sorting enabled
|
||||
activeForThisPlayer = playerConfig.getBoolean("sortingEnabled");
|
||||
invActiveForThisPlayer = playerConfig.getBoolean("invSortingEnabled");
|
||||
middleClick = playerConfig.getBoolean("middleClick");
|
||||
shiftClick = playerConfig.getBoolean("shiftClick");
|
||||
doubleClick = playerConfig.getBoolean("doubleClick");
|
||||
shiftRightClick = playerConfig.getBoolean("shiftRightClick");
|
||||
}
|
||||
|
||||
JeffChestSortPlayerSetting newSettings = new JeffChestSortPlayerSetting(activeForThisPlayer,invActiveForThisPlayer,middleClick,shiftClick,doubleClick,shiftRightClick);
|
||||
|
||||
// when "show-message-again-after-logout" is enabled, we don't care if the
|
||||
// player already saw the message
|
||||
if (!plugin.getConfig().getBoolean("show-message-again-after-logout")) {
|
||||
newSettings.hasSeenMessage = playerConfig.getBoolean("hasSeenMessage");
|
||||
}
|
||||
|
||||
// Finally add the PlayerSetting object to the map
|
||||
plugin.PerPlayerSettings.put(uniqueId.toString(), newSettings);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
plugin.unregisterPlayer(event.getPlayer());
|
||||
@ -127,9 +61,9 @@ public class JeffChestSortListener implements Listener {
|
||||
Player p = (Player) event.getInventory().getHolder();
|
||||
|
||||
if(!p.hasPermission("chestsort.use.inventory")) return;
|
||||
registerPlayerIfNeeded(p);
|
||||
plugin.registerPlayerIfNeeded(p);
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(p.getUniqueId().toString());
|
||||
if(!setting.invSortingEnabled) return;
|
||||
|
||||
plugin.organizer.sortInventory(p.getInventory(),9,35);
|
||||
@ -251,12 +185,12 @@ public class JeffChestSortListener implements Listener {
|
||||
}
|
||||
|
||||
// Fixes exception when using Spigot's stupid /reload command
|
||||
registerPlayerIfNeeded(p);
|
||||
plugin.registerPlayerIfNeeded(p);
|
||||
|
||||
// Get the current player's settings
|
||||
// We do not immediately cancel when sorting is disabled because we might want
|
||||
// to show the hint message
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
// Show "how to enable ChestSort" message when ALL of the following criteria are
|
||||
// met:
|
||||
@ -323,7 +257,7 @@ public class JeffChestSortListener implements Listener {
|
||||
|
||||
Player p = (Player) event.getWhoClicked();
|
||||
|
||||
registerPlayerIfNeeded(p);
|
||||
plugin.registerPlayerIfNeeded(p);
|
||||
|
||||
if(!plugin.getConfig().getBoolean("allow-hotkeys")) {
|
||||
return;
|
||||
@ -349,7 +283,7 @@ public class JeffChestSortListener implements Listener {
|
||||
|
||||
boolean sort = false;
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
// Do not sort the GUI inventory
|
||||
if(event.getClickedInventory() == setting.guiInventory) {
|
||||
@ -439,55 +373,5 @@ public class JeffChestSortListener implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
void onGUIInteract(InventoryClickEvent event) {
|
||||
if(plugin.hotkeyGUI==false) {
|
||||
return;
|
||||
}
|
||||
if(!(event.getWhoClicked() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
Player p = (Player) event.getWhoClicked();
|
||||
registerPlayerIfNeeded(p);
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
if(setting.guiInventory==null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.getClickedInventory()==null) {
|
||||
return;
|
||||
}
|
||||
if(!event.getClickedInventory().equals(setting.guiInventory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only get this far if the player has clicked inside his GUI inventory
|
||||
event.setCancelled(true);
|
||||
if(event.getClick() != ClickType.LEFT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.getSlot() == JeffChestSortSettingsGUI.slotMiddleClick) {
|
||||
setting.middleClick = !setting.middleClick;
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
}
|
||||
else if(event.getSlot() == JeffChestSortSettingsGUI.slotShiftClick) {
|
||||
setting.shiftClick = !setting.shiftClick;
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
} else if(event.getSlot() == JeffChestSortSettingsGUI.slotDoubleClick) {
|
||||
setting.doubleClick = !setting.doubleClick;
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
} else if(event.getSlot() == JeffChestSortSettingsGUI.slotShiftRightClick) {
|
||||
setting.shiftRightClick = !setting.shiftRightClick;
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,14 +22,59 @@ public class JeffChestSortPlayerSetting {
|
||||
|
||||
// Did we already show the message how to activate sorting?
|
||||
boolean hasSeenMessage = false;
|
||||
|
||||
// Do we have to save these settings?
|
||||
boolean changed = false;
|
||||
|
||||
JeffChestSortPlayerSetting(boolean sortingEnabled, boolean invSortingEnabled, boolean middleClick, boolean shiftClick, boolean doubleClick, boolean shiftRightClick) {
|
||||
JeffChestSortPlayerSetting(boolean sortingEnabled, boolean invSortingEnabled, boolean middleClick, boolean shiftClick, boolean doubleClick, boolean shiftRightClick, boolean changed) {
|
||||
this.sortingEnabled = sortingEnabled;
|
||||
this.middleClick = middleClick;
|
||||
this.shiftClick = shiftClick;
|
||||
this.doubleClick = doubleClick;
|
||||
this.shiftRightClick = shiftRightClick;
|
||||
this.invSortingEnabled = invSortingEnabled;
|
||||
this.changed = changed;
|
||||
}
|
||||
|
||||
void toggleMiddleClick() {
|
||||
middleClick = !middleClick;
|
||||
changed = true;
|
||||
}
|
||||
void toggleShiftClick() {
|
||||
shiftClick = !shiftClick;
|
||||
changed = true;
|
||||
}
|
||||
void toggleDoubleClick() {
|
||||
doubleClick = !doubleClick;
|
||||
changed = true;
|
||||
}
|
||||
void toggleShiftRightClick() {
|
||||
shiftRightClick = !shiftRightClick;
|
||||
changed = true;
|
||||
}
|
||||
void enableChestSorting() {
|
||||
sortingEnabled = true;
|
||||
changed = true;
|
||||
}
|
||||
void disableChestSorting() {
|
||||
sortingEnabled = false;
|
||||
changed = true;
|
||||
}
|
||||
void toggleChestSorting() {
|
||||
sortingEnabled = !sortingEnabled;
|
||||
changed = true;
|
||||
}
|
||||
void enableInvSorting() {
|
||||
invSortingEnabled = true;
|
||||
changed = true;
|
||||
}
|
||||
void disableInvSorting() {
|
||||
invSortingEnabled = false;
|
||||
changed = true;
|
||||
}
|
||||
void toggleInvSorting() {
|
||||
invSortingEnabled = !invSortingEnabled;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
|
||||
/*
|
||||
|
||||
@ -18,9 +15,6 @@ import java.io.BufferedWriter;
|
||||
|
||||
Please DO NOT post bug reports or feature requests in the review section at SpigotMC.org. Thank you.
|
||||
|
||||
NOTE: The project has been converted to maven by Azzurite (thanks again). You will need to
|
||||
`mvn install` to create a working .jar.
|
||||
|
||||
=============================================================================================
|
||||
|
||||
TECHNICAL INFORMATION:
|
||||
@ -32,6 +26,9 @@ import java.io.BufferedWriter;
|
||||
|
||||
*/
|
||||
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
@ -47,7 +44,6 @@ import java.util.UUID;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@ -59,7 +55,7 @@ import de.jeffclan.utils.Utils;
|
||||
public class JeffChestSortPlugin extends JavaPlugin {
|
||||
|
||||
// We need a map to store each player's settings
|
||||
Map<String, JeffChestSortPlayerSetting> PerPlayerSettings = new HashMap<String, JeffChestSortPlayerSetting>();
|
||||
Map<String, JeffChestSortPlayerSetting> perPlayerSettings = new HashMap<String, JeffChestSortPlayerSetting>();
|
||||
JeffChestSortMessages messages;
|
||||
JeffChestSortOrganizer organizer;
|
||||
JeffChestSortUpdateChecker updateChecker;
|
||||
@ -69,7 +65,7 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
ArrayList<String> disabledWorlds;
|
||||
int currentConfigVersion = 22;
|
||||
boolean usingMatchingConfig = true;
|
||||
boolean debug = false;
|
||||
protected boolean debug = false;
|
||||
boolean verbose = true;
|
||||
boolean hotkeyGUI = true;
|
||||
|
||||
@ -163,7 +159,6 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
|
||||
getConfig().addDefault("hook-crackshot", true);
|
||||
getConfig().addDefault("hook-crackshot-prefix", "crackshot_weapon");
|
||||
|
||||
getConfig().addDefault("hook-inventorypages", true);
|
||||
|
||||
getConfig().addDefault("verbose", true); // Prints some information in onEnable()
|
||||
@ -193,31 +188,6 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
getLogger().warning("==============================================");
|
||||
}
|
||||
|
||||
private void renameConfigIfTooOld() {
|
||||
getLogger().warning("========================================================");
|
||||
getLogger().warning("You are using a config file that has been generated");
|
||||
getLogger().warning("prior to ChestSort version 2.0.0.");
|
||||
getLogger().warning("To allow everyone to use the new features, your config");
|
||||
getLogger().warning("has been renamed to config.old.yml and a new one has");
|
||||
getLogger().warning("been generated. Please examine the new config file to");
|
||||
getLogger().warning("see the new possibilities and adjust your settings.");
|
||||
getLogger().warning("========================================================");
|
||||
|
||||
File configFile = new File(getDataFolder().getAbsolutePath() + File.separator + "config.yml");
|
||||
File oldConfigFile = new File(getDataFolder().getAbsolutePath() + File.separator + "config.old.yml");
|
||||
if (oldConfigFile.getAbsoluteFile().exists()) {
|
||||
oldConfigFile.getAbsoluteFile().delete();
|
||||
}
|
||||
configFile.getAbsoluteFile().renameTo(oldConfigFile.getAbsoluteFile());
|
||||
saveDefaultConfig();
|
||||
try {
|
||||
getConfig().load(configFile.getAbsoluteFile());
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
getLogger().warning("Could not load freshly generated config file!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// We have to unregister every player to save their perPlayerSettings
|
||||
@ -233,12 +203,6 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
mcVersion = tmpVersion.substring(tmpVersion.lastIndexOf('.') + 1);
|
||||
tmpVersion = mcVersion.substring(mcVersion.indexOf("_")+1);
|
||||
mcMinorVersion = Integer.parseInt(tmpVersion.substring(0,tmpVersion.indexOf("_")));
|
||||
|
||||
//getLogger().info("Running MC version 1."+mcMinorVersion);
|
||||
// if(mcMinorVersion < 9) {
|
||||
// getLogger().info("You are running a Minecraft version below 1.9. Hotkey GUI will be disabled.");
|
||||
// hotkeyGUI = false;
|
||||
// }
|
||||
|
||||
// Create the config file, including checks for old config versions, and load
|
||||
// the default values for unset options
|
||||
@ -281,19 +245,25 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
// the Organizer to sort inventories when a player closes a chest, shulkerbox or
|
||||
// barrel inventory
|
||||
listener = new JeffChestSortListener(this);
|
||||
|
||||
//hotbarRefiller = new JeffChestSortHotbarRefiller(this);
|
||||
|
||||
// The sorting method will determine how stuff is sorted
|
||||
sortingMethod = getConfig().getString("sorting-method");
|
||||
|
||||
// Register the events for our Listener
|
||||
getServer().getPluginManager().registerEvents(listener, this);
|
||||
|
||||
// Register events for the GUI interaction
|
||||
getServer().getPluginManager().registerEvents(settingsGUI, this);
|
||||
|
||||
// Create the CommandExecutor, register commands and set their TabCompleter
|
||||
JeffChestSortCommandExecutor commandExecutor = new JeffChestSortCommandExecutor(this);
|
||||
JeffChestSortChestSortCommand chestsortCommandExecutor = new JeffChestSortChestSortCommand(this);
|
||||
JeffChestSortTabCompleter tabCompleter = new JeffChestSortTabCompleter();
|
||||
this.getCommand("chestsort").setExecutor(commandExecutor);
|
||||
this.getCommand("chestsort").setExecutor(chestsortCommandExecutor);
|
||||
this.getCommand("chestsort").setTabCompleter(tabCompleter);
|
||||
this.getCommand("invsort").setExecutor(commandExecutor);
|
||||
JeffChestSortInvSortCommand invsortCommandExecutor = new JeffChestSortInvSortCommand(this);
|
||||
this.getCommand("invsort").setExecutor(invsortCommandExecutor);
|
||||
this.getCommand("invsort").setTabCompleter(tabCompleter);
|
||||
|
||||
// Does anyone actually need this?
|
||||
@ -315,7 +285,6 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
// Check for updates (async, of course)
|
||||
|
||||
// When set to true, we check for updates right now, and every 24 hours (see
|
||||
// updateCheckInterval)
|
||||
if (getConfig().getString("check-for-updates", "true").equalsIgnoreCase("true")) {
|
||||
@ -333,6 +302,8 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
|
||||
registerMetrics();
|
||||
|
||||
// When dump is set to true in config.yml, we dump all items with their categories
|
||||
// to find out which items are still missing in the category files
|
||||
if(getConfig().getBoolean("dump")) {
|
||||
try {
|
||||
dump();
|
||||
@ -341,7 +312,6 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getCategoryList() {
|
||||
@ -483,13 +453,13 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
// server ;) I am sometimes getting stacktraces although it is clearly stated
|
||||
// that /reload is NOT
|
||||
// supported. So, here is a quick fix
|
||||
if (PerPlayerSettings == null) {
|
||||
PerPlayerSettings = new HashMap<String, JeffChestSortPlayerSetting>();
|
||||
if (perPlayerSettings == null) {
|
||||
perPlayerSettings = new HashMap<String, JeffChestSortPlayerSetting>();
|
||||
}
|
||||
listener.registerPlayerIfNeeded(p);
|
||||
listener.plugin.registerPlayerIfNeeded(p);
|
||||
// End of quick fix
|
||||
|
||||
return PerPlayerSettings.get(p.getUniqueId().toString()).sortingEnabled;
|
||||
return perPlayerSettings.get(p.getUniqueId().toString()).sortingEnabled;
|
||||
}
|
||||
|
||||
// Unregister a player and save their settings in the playerdata folder
|
||||
@ -501,8 +471,9 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
// When using /reload or some other obscure features, it can happen that players
|
||||
// are online
|
||||
// but not registered. So, we only continue when the player has been registered
|
||||
if (PerPlayerSettings.containsKey(uniqueId.toString())) {
|
||||
JeffChestSortPlayerSetting setting = PerPlayerSettings.get(p.getUniqueId().toString());
|
||||
if (perPlayerSettings.containsKey(uniqueId.toString())) {
|
||||
JeffChestSortPlayerSetting setting = perPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
File playerFile = new File(getDataFolder() + File.separator + "playerdata",
|
||||
p.getUniqueId().toString() + ".yml");
|
||||
YamlConfiguration playerConfig = YamlConfiguration.loadConfiguration(playerFile);
|
||||
@ -514,12 +485,18 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
playerConfig.set("doubleClick",setting.doubleClick);
|
||||
playerConfig.set("shiftRightClick",setting.shiftRightClick);
|
||||
try {
|
||||
playerConfig.save(playerFile);
|
||||
// Only saved if the config has been changed
|
||||
if(setting.changed) {
|
||||
if(debug) {
|
||||
getLogger().info("PlayerSettings for "+p.getName()+" have changed, saving to file.");
|
||||
}
|
||||
playerConfig.save(playerFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
PerPlayerSettings.remove(uniqueId.toString());
|
||||
perPlayerSettings.remove(uniqueId.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,4 +512,68 @@ public class JeffChestSortPlugin extends JavaPlugin {
|
||||
bw.close();
|
||||
}
|
||||
|
||||
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("hotkeys.middle-click"));
|
||||
playerConfig.addDefault("shiftClick", getConfig().getBoolean("hotkeys.shift-click"));
|
||||
playerConfig.addDefault("doubleClick", getConfig().getBoolean("hotkeys.double-click"));
|
||||
playerConfig.addDefault("shiftRightClick", getConfig().getBoolean("hotkeys.shift-right-click"));
|
||||
|
||||
boolean activeForThisPlayer = false;
|
||||
boolean invActiveForThisPlayer = false;
|
||||
boolean middleClick, shiftClick, doubleClick, shiftRightClick;
|
||||
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("hotkeys.middle-click");
|
||||
shiftClick = getConfig().getBoolean("hotkeys.shift-click");
|
||||
doubleClick = getConfig().getBoolean("hotkeys.double-click");
|
||||
shiftRightClick = getConfig().getBoolean("hotkeys.shift-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");
|
||||
middleClick = playerConfig.getBoolean("middleClick");
|
||||
shiftClick = playerConfig.getBoolean("shiftClick");
|
||||
doubleClick = playerConfig.getBoolean("doubleClick");
|
||||
shiftRightClick = playerConfig.getBoolean("shiftRightClick");
|
||||
}
|
||||
|
||||
JeffChestSortPlayerSetting newSettings = new JeffChestSortPlayerSetting(activeForThisPlayer,invActiveForThisPlayer,middleClick,shiftClick,doubleClick,shiftRightClick,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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,12 +4,16 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class JeffChestSortSettingsGUI {
|
||||
public class JeffChestSortSettingsGUI implements Listener {
|
||||
|
||||
JeffChestSortPlugin plugin;
|
||||
|
||||
@ -32,17 +36,6 @@ public class JeffChestSortSettingsGUI {
|
||||
ItemStack getItem(boolean active, Hotkey hotkey) {
|
||||
ItemStack is = null;
|
||||
String suffix;
|
||||
//Material green = Material.getMaterial("GREEN_WOOL");
|
||||
//Material red = Material.getMaterial("RED_WOOL");
|
||||
//Material green = Material.GREEN_WOOL;
|
||||
//Material red = Material.RED_WOOL;
|
||||
|
||||
// if(green==null || red==null) {
|
||||
// //plugin.getLogger().warning("Using unsupported Minecraft version");
|
||||
// green = Material.EMERALD_BLOCK;
|
||||
// red = Material.REDSTONE_BLOCK;
|
||||
// //return null;
|
||||
// }
|
||||
|
||||
if(active) {
|
||||
is = new ItemStack(green);
|
||||
@ -80,13 +73,7 @@ public class JeffChestSortSettingsGUI {
|
||||
void openGUI(Player player) {
|
||||
Inventory inventory = createGUI("ChestSort", player);
|
||||
|
||||
JeffChestSortPlayerSetting setting = plugin.PerPlayerSettings.get(player.getUniqueId().toString());
|
||||
|
||||
// Test if running 1.13 or later
|
||||
// if(Material.getMaterial("GREEN_WOOL") == null) {
|
||||
// player.sendMessage(plugin.messages.MSG_ERR_HOTKEYSDISABLED);
|
||||
// return;
|
||||
// }
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(player.getUniqueId().toString());
|
||||
|
||||
inventory.setItem(slotMiddleClick, getItem(setting.middleClick,Hotkey.MiddleClick));
|
||||
inventory.setItem(slotShiftClick, getItem(setting.shiftClick,Hotkey.ShiftClick));
|
||||
@ -101,4 +88,54 @@ public class JeffChestSortSettingsGUI {
|
||||
Inventory inventory = Bukkit.createInventory(inventoryHolder, InventoryType.CHEST, name);
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
void onGUIInteract(InventoryClickEvent event) {
|
||||
if(plugin.hotkeyGUI==false) {
|
||||
return;
|
||||
}
|
||||
if(!(event.getWhoClicked() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
Player p = (Player) event.getWhoClicked();
|
||||
plugin.listener.plugin.registerPlayerIfNeeded(p);
|
||||
JeffChestSortPlayerSetting setting = plugin.perPlayerSettings.get(p.getUniqueId().toString());
|
||||
|
||||
if(setting.guiInventory==null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.getClickedInventory()==null) {
|
||||
return;
|
||||
}
|
||||
if(!event.getClickedInventory().equals(setting.guiInventory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only get this far if the player has clicked inside his GUI inventory
|
||||
event.setCancelled(true);
|
||||
if(event.getClick() != ClickType.LEFT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.getSlot() == JeffChestSortSettingsGUI.slotMiddleClick) {
|
||||
setting.toggleMiddleClick();
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
}
|
||||
else if(event.getSlot() == JeffChestSortSettingsGUI.slotShiftClick) {
|
||||
setting.toggleShiftClick();
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
} else if(event.getSlot() == JeffChestSortSettingsGUI.slotDoubleClick) {
|
||||
setting.toggleDoubleClick();
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
} else if(event.getSlot() == JeffChestSortSettingsGUI.slotShiftRightClick) {
|
||||
setting.toggleShiftRightClick();
|
||||
plugin.settingsGUI.openGUI(p);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,539 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
|
||||
package de.jeffclan.JeffChestSort;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class MetricsLite {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 7;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://report.mcstats.org";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/plugin/%s";
|
||||
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private final static int PING_INTERVAL = 15;
|
||||
|
||||
/**
|
||||
* The plugin this metrics submits for
|
||||
*/
|
||||
private final Plugin plugin;
|
||||
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final YamlConfiguration configuration;
|
||||
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
|
||||
/**
|
||||
* Lock for synchronization
|
||||
*/
|
||||
private final Object optOutLock = new Object();
|
||||
|
||||
/**
|
||||
* Id of the scheduled task
|
||||
*/
|
||||
private volatile BukkitTask task = null;
|
||||
|
||||
public MetricsLite(Plugin plugin) throws IOException {
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null");
|
||||
}
|
||||
|
||||
this.plugin = plugin;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = YamlConfiguration.loadConfiguration(configurationFile);
|
||||
|
||||
// add some defaults
|
||||
configuration.addDefault("opt-out", false);
|
||||
configuration.addDefault("guid", UUID.randomUUID().toString());
|
||||
configuration.addDefault("debug", false);
|
||||
|
||||
// Do we need to create the file?
|
||||
if (configuration.get("guid", null) == null) {
|
||||
configuration.options().header("http://mcstats.org").copyDefaults(true);
|
||||
configuration.save(configurationFile);
|
||||
}
|
||||
|
||||
// Load the guid then
|
||||
guid = configuration.getString("guid");
|
||||
debug = configuration.getBoolean("debug", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send
|
||||
* the initial data to the metrics backend, and then after that it will post in increments of
|
||||
* PING_INTERVAL * 1200 ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
synchronized (optOutLock) {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is metrics already running?
|
||||
if (task != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Begin hitting the server with glorious data
|
||||
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
|
||||
|
||||
private boolean firstPost = true;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// This has to be synchronized or it can collide with the disable method.
|
||||
synchronized (optOutLock) {
|
||||
// Disable Task, if it is running and the server owner decided to opt-out
|
||||
if (isOptOut() && task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
|
||||
// We use the inverse of firstPost because if it is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to FALSE
|
||||
// Each time thereafter it will evaluate to TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
|
||||
// After the first post we set firstPost to false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0, PING_INTERVAL * 1200);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
synchronized (optOutLock) {
|
||||
try {
|
||||
// Reload the metrics file
|
||||
configuration.load(getConfigFile());
|
||||
} catch (IOException ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return configuration.getBoolean("opt-out", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// This has to be synchronized or it can collide with the check in the task.
|
||||
synchronized (optOutLock) {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.set("opt-out", false);
|
||||
configuration.save(configurationFile);
|
||||
}
|
||||
|
||||
// Enable Task, if it is not running
|
||||
if (task == null) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// This has to be synchronized or it can collide with the check in the task.
|
||||
synchronized (optOutLock) {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.set("opt-out", true);
|
||||
configuration.save(configurationFile);
|
||||
}
|
||||
|
||||
// Disable Task, if it is running
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
|
||||
// is to abuse the plugin object we already have
|
||||
// plugin.getDataFolder() => base/plugins/PluginA/
|
||||
// pluginsFolder => base/plugins/
|
||||
// The base is not necessarily relative to the startup directory.
|
||||
File pluginsFolder = plugin.getDataFolder().getParentFile();
|
||||
|
||||
// return => base/plugins/PluginMetrics/config.yml
|
||||
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the online player (backwards compatibility)
|
||||
*
|
||||
* @return online player amount
|
||||
*/
|
||||
private int getOnlinePlayers() {
|
||||
try {
|
||||
Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers");
|
||||
if(onlinePlayerMethod.getReturnType().equals(Collection.class)) {
|
||||
return ((Collection<?>)onlinePlayerMethod.invoke(Bukkit.getServer())).size();
|
||||
} else {
|
||||
return ((Player[])onlinePlayerMethod.invoke(Bukkit.getServer())).length;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
PluginDescriptionFile description = plugin.getDescription();
|
||||
String pluginName = description.getName();
|
||||
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
|
||||
String pluginVersion = description.getVersion();
|
||||
String serverVersion = Bukkit.getVersion();
|
||||
int playersOnline = this.getOnlinePlayers();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
StringBuilder json = new StringBuilder(1024);
|
||||
json.append('{');
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
appendJSONPair(json, "guid", guid);
|
||||
appendJSONPair(json, "plugin_version", pluginVersion);
|
||||
appendJSONPair(json, "server_version", serverVersion);
|
||||
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
appendJSONPair(json, "osname", osname);
|
||||
appendJSONPair(json, "osarch", osarch);
|
||||
appendJSONPair(json, "osversion", osversion);
|
||||
appendJSONPair(json, "cores", Integer.toString(coreCount));
|
||||
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
|
||||
appendJSONPair(json, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
appendJSONPair(json, "ping", "1");
|
||||
}
|
||||
|
||||
// close json
|
||||
json.append('}');
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
|
||||
byte[] uncompressed = json.toString().getBytes();
|
||||
byte[] compressed = gzip(json.toString());
|
||||
|
||||
// Headers
|
||||
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
|
||||
connection.addRequestProperty("Content-Type", "application/json");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
if (debug) {
|
||||
System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
|
||||
}
|
||||
|
||||
// Write the data
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(compressed);
|
||||
os.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
os.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
|
||||
if (response == null) {
|
||||
response = "null";
|
||||
} else if (response.startsWith("7")) {
|
||||
response = response.substring(response.startsWith("7,") ? 2 : 1);
|
||||
}
|
||||
|
||||
throw new IOException(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GZip compress a string of bytes
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static byte[] gzip(String input) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzos = null;
|
||||
|
||||
try {
|
||||
gzos = new GZIPOutputStream(baos);
|
||||
gzos.write(input.getBytes("UTF-8"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (gzos != null) try {
|
||||
gzos.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a json encoded key/value pair to the given string builder.
|
||||
*
|
||||
* @param json
|
||||
* @param key
|
||||
* @param value
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
|
||||
boolean isValueNumeric = false;
|
||||
|
||||
try {
|
||||
if (value.equals("0") || !value.endsWith("0")) {
|
||||
Double.parseDouble(value);
|
||||
isValueNumeric = true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
isValueNumeric = false;
|
||||
}
|
||||
|
||||
if (json.charAt(json.length() - 1) != '{') {
|
||||
json.append(',');
|
||||
}
|
||||
|
||||
json.append(escapeJSON(key));
|
||||
json.append(':');
|
||||
|
||||
if (isValueNumeric) {
|
||||
json.append(value);
|
||||
} else {
|
||||
json.append(escapeJSON(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string to create a valid JSON string
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String escapeJSON(String text) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append('"');
|
||||
for (int index = 0; index < text.length(); index++) {
|
||||
char chr = text.charAt(index);
|
||||
|
||||
switch (chr) {
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append('\\');
|
||||
builder.append(chr);
|
||||
break;
|
||||
case '\b':
|
||||
builder.append("\\b");
|
||||
break;
|
||||
case '\t':
|
||||
builder.append("\\t");
|
||||
break;
|
||||
case '\n':
|
||||
builder.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.append("\\r");
|
||||
break;
|
||||
default:
|
||||
if (chr < ' ') {
|
||||
String t = "000" + Integer.toHexString(chr);
|
||||
builder.append("\\u" + t.substring(t.length() - 4));
|
||||
} else {
|
||||
builder.append(chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.append('"');
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String urlEncode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
main: de.jeffclan.JeffChestSort.JeffChestSortPlugin
|
||||
name: ChestSort
|
||||
version: 7.6.1
|
||||
version: 7.7-pre1
|
||||
api-version: 1.13
|
||||
description: Allows automatic chest sorting
|
||||
author: mfnalex
|
||||
@ -12,16 +12,22 @@ softdepend: [CrackShot, InventoryPages]
|
||||
commands:
|
||||
chestsort:
|
||||
description: Toggle automatic chest sorting.
|
||||
usage: /<command>
|
||||
usage: /<command> [on|off|toggle]
|
||||
aliases: sort
|
||||
permission: chestsort.use
|
||||
invsort:
|
||||
description: Sorts the player's inventory. When no option is specified, only the regular inventory (excluding the hotbar) is sorted.
|
||||
usage: /<command> [inv|hotbar|all]
|
||||
description: Toggle automatic inventory sorting or sorts the player's inventory. When no option is specified, only the regular inventory (excluding the hotbar) is sorted.
|
||||
usage: /<command> [on|off|toggle|inv|hotbar|all]
|
||||
aliases: [isort,inventorysort]
|
||||
permission: chestsort.use.inventory
|
||||
refill:
|
||||
description: Allows auto-refilling items in the hotbar
|
||||
usage: /<command> [on|off|toggle]
|
||||
permission: chestsort.use.refill
|
||||
permissions:
|
||||
chestsort.use:
|
||||
description: Allows chest sorting
|
||||
chestsort.use.inventory:
|
||||
description: Allows inventory sorting
|
||||
chestsort.use.refill:
|
||||
description: Allows auto-refilling the hotbar
|
Loading…
Reference in New Issue
Block a user