8.11.1-SNAPSHOT

This commit is contained in:
mfnalex 2020-06-24 21:31:25 +02:00
parent 61b88c8d94
commit 5b16c3870d
6 changed files with 569 additions and 601 deletions

View File

@ -1,7 +1,8 @@
# Changelog
## 8.11.1
## 8.11.1-SNAPSHOT
- Improved help messages
- Huge code cleanup
- Improved performance by caching Reflection checks in the Minepacks hook
## 8.11.0
- Adjustet Left-Click / Right-Click hotkeys:

View File

@ -9,7 +9,7 @@
<name>JeffChestSort</name>
<url>https://www.chestsort.de</url>
<description>Automatically sorts your chests!</description>
<version>8.11.1</version>
<version>8.11.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>

View File

@ -1,9 +1,9 @@
package de.jeff_media.ChestSort;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import de.jeff_media.ChestSort.hooks.CrackShotHook;
import de.jeff_media.ChestSort.hooks.InventoryPagesHook;
import de.jeff_media.ChestSort.utils.CategoryLinePair;
import de.jeff_media.ChestSort.utils.TypeMatchPositionPair;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
@ -19,10 +19,9 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import de.jeff_media.ChestSort.hooks.CrackShotHook;
import de.jeff_media.ChestSort.hooks.InventoryPagesHook;
import de.jeff_media.ChestSort.utils.CategoryLinePair;
import de.jeff_media.ChestSort.utils.TypeMatchPositionPair;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class ChestSortOrganizer {
@ -37,25 +36,20 @@ public class ChestSortOrganizer {
* they are already alphabetically in the right order
*/
// All available colors in the game. We will strip this from the item names and
// keep the color in a separate variable
static final String[] colors = {"white", "orange", "magenta", "light_blue", "light_gray", "yellow", "lime", "pink",
"gray", "cyan", "purple", "blue", "brown", "green", "red", "black"};
// The same applies for wood. We strip the wood name from the item name and keep
// it in the above mentioned color variable
static final String[] woodNames = {"acacia", "birch", "jungle", "oak", "spruce", "dark_oak"};
private static final int maxInventorySize = 54;
private static final int playerInvStartSlot = 9; // Inclusive
private static final int playerInvEndSlot = 35; // Inclusive
private static final String emptyPlaceholderString = "~";
final ChestSortPlugin plugin;
final CrackShotHook crackShotHook;
final InventoryPagesHook inventoryPagesHook;
private static final int maxInventorySize=54;
private static final int playerInvStartSlot=9; // Inclusive
private static final int playerInvEndSlot=35; // Inclusive
// All available colors in the game. We will strip this from the item names and
// keep the color in a separate variable
static final String[] colors = { "white", "orange", "magenta", "light_blue", "light_gray", "yellow", "lime", "pink",
"gray", "cyan", "purple", "blue", "brown", "green", "red", "black" };
// The same applies for wood. We strip the wood name from the item name and keep
// it in the above mentioned color variable
static final String[] woodNames = { "acacia", "birch", "jungle", "oak", "spruce", "dark_oak" };
private static final String emptyPlaceholderString = "~";
// We store a list of all Category objects
final ArrayList<ChestSortCategory> categories = new ArrayList<>();
final ArrayList<String> stickyCategoryNames = new ArrayList<>();
@ -97,9 +91,9 @@ public class ChestSortOrganizer {
}
// Make categories sticky
for(String catName : stickyCategoryNames) {
for(ChestSortCategory cat : categories) {
if(catName.equalsIgnoreCase(cat.name)) {
for (String catName : stickyCategoryNames) {
for (ChestSortCategory cat : categories) {
if (catName.equalsIgnoreCase(cat.name)) {
cat.setSticky();
}
}
@ -110,6 +104,37 @@ public class ChestSortOrganizer {
}
static int getNumberOfEnchantments(ItemStack is) {
int totalEnchants = 0;
//if(!is.getItemMeta().hasEnchants()) return 0;
if (is.getItemMeta() instanceof EnchantmentStorageMeta) {
EnchantmentStorageMeta storageMeta = (EnchantmentStorageMeta) is.getItemMeta();
Map<Enchantment, Integer> storedEnchants = storageMeta.getStoredEnchants();
for (int level : storedEnchants.values()) {
totalEnchants += level;
}
}
Map<Enchantment, Integer> enchants = is.getItemMeta().getEnchants();
for (int level : enchants.values()) {
totalEnchants += level;
}
return totalEnchants;
}
static boolean doesInventoryContain(Inventory inv, Material mat) {
for (ItemStack item : inv.getContents()) {
if (item == null) continue;
if (item.getType() == mat) {
return true;
}
}
return false;
}
// Returns an array with all typematches listed in the category file
TypeMatchPositionPair[] loadCategoryFile(File file) throws FileNotFoundException {
// This is called "sticky" in the category files. When it is enabled, it has the
@ -211,7 +236,7 @@ public class ChestSortOrganizer {
}
}
// when typeName is exactly "log", change to "log_a" so it gets sorted before the stripped variants
if(typeName.equals("log")) {
if (typeName.equals("log")) {
typeName = "log_a";
}
@ -311,7 +336,8 @@ public class ChestSortOrganizer {
}
}
}
} catch (NoSuchMethodException | SecurityException ignored) { }
} catch (NoSuchMethodException | SecurityException ignored) {
}
// potionEffects = potionEffects.substring(0, potionEffects.length()-1);
}
@ -320,10 +346,10 @@ public class ChestSortOrganizer {
String hookChangedName = item.getType().name();
// CrackShot Support Start
if(plugin.hookCrackShot) {
if(crackShotHook.getCrackShotWeaponName(item)!=null) {
if (plugin.hookCrackShot) {
if (crackShotHook.getCrackShotWeaponName(item) != null) {
typeName = plugin.getConfig().getString("hook-crackshot-prefix") + "_" + crackShotHook.getCrackShotWeaponName(item);
color="";
color = "";
hookChangedName = typeName;
}
}
@ -333,8 +359,8 @@ public class ChestSortOrganizer {
String categoryName = categoryLinePair.getCategoryName();
String categorySticky = categoryName;
String lineNumber = getCategoryLinePair(hookChangedName).getFormattedPosition();
if(stickyCategoryNames.contains(categoryName)) {
categorySticky = categoryName+"~"+lineNumber;
if (stickyCategoryNames.contains(categoryName)) {
categorySticky = categoryName + "~" + lineNumber;
}
String customName = (plugin.debug) ? "~customName~" : emptyPlaceholderString;
@ -349,14 +375,14 @@ public class ChestSortOrganizer {
}
// Put enchanted items before unenchanted ones
typeName = typeName + String.format("%05d", 10000-getNumberOfEnchantments(item));
typeName = typeName + String.format("%05d", 10000 - getNumberOfEnchantments(item));
// Generate the strings that finally are used for sorting.
// They are generated according to the config.yml's sorting-method option
String sortableString = plugin.sortingMethod.replaceAll(",", "|");
sortableString = sortableString.replace("{itemsFirst}", String.valueOf(itemsFirst));
sortableString = sortableString.replace("{blocksFirst}", String.valueOf(blocksFirst));
sortableString = sortableString.replace("{name}", typeName+potionEffect);
sortableString = sortableString.replace("{name}", typeName + potionEffect);
sortableString = sortableString.replace("{color}", color);
sortableString = sortableString.replace("{category}", categorySticky);
sortableString = sortableString.replace("{keepCategoryOrder}", lineNumber);
@ -376,10 +402,10 @@ public class ChestSortOrganizer {
void sortInventory(Inventory inv, int startSlot, int endSlot) {
Class<? extends Inventory> invClass = inv.getClass();
try {
if(invClass.getMethod("getLocation", null) != null) {
if (invClass.getMethod("getLocation", null) != null) {
// This whole try/catch fixes MethodNotFoundException when using inv.getLocation in Spigot 1.8.
}
if(inv.getLocation() != null) {
if (inv.getLocation() != null) {
ChestSortEvent chestSortEvent = new ChestSortEvent(inv);
chestSortEvent.loc = inv.getLocation();
Bukkit.getPluginManager().callEvent(chestSortEvent);
@ -420,37 +446,23 @@ public class ChestSortOrganizer {
//unsortableSlots.add(i);
}
}*/
// Do not move Minepacks' backpacks
if(plugin.hookMinepacks) {
for(int i = startSlot; i<= endSlot; i++) {
if(plugin.listener.minepacksHook.isMinepacksBackpack(items[i])) {
items[i] = null;
unsortableSlots.add(i);
}
}
}
// If InventoryPages is installed: get rid of the buttons
if(plugin.hookInventoryPages) {
for(int i = startSlot; i<= endSlot; i++) {
if(inventoryPagesHook.isButton(items[i], i,inv)) {
//System.out.println("Inventory Pages Button found at slot " + i);
items[i] = null;
unsortableSlots.add(i);
}
}
}
// Do not move ItemStacks with more than 64 items
for(int i = startSlot; i<= endSlot; i++) {
if(isOversizedStack(items[i])) {
// Check for
// - Minepacks backpacks
// - Inventorypages buttons
// - ItemStacks with more than 64 items
for (int i = startSlot; i <= endSlot; i++) {
if ((plugin.hookMinepacks && plugin.listener.minepacksHook.isMinepacksBackpack(items[i]))
|| (plugin.hookInventoryPages && inventoryPagesHook.isButton(items[i], i, inv))
|| isOversizedStack(items[i])) {
items[i] = null;
unsortableSlots.add(i);
}
}
// Remove the stuff from the original inventory
for (int i = startSlot; i <= endSlot; i++) {
if(!unsortableSlots.contains(i))
{
if (!unsortableSlots.contains(i)) {
inv.clear(i);
}
}
@ -467,8 +479,6 @@ public class ChestSortOrganizer {
// We need the new list as array. So why did'nt we take an array from the
// beginning?
// Because I did not bother to count the number of non-null items beforehand.
// TODO: Feel free to make a Pull request if you want to save your server a few
// nanoseconds :)
ItemStack[] nonNullItems = nonNullItemsList.toArray(new ItemStack[0]);
// Sort the array with ItemStacks according to each ItemStacks' sortable String
@ -500,49 +510,17 @@ public class ChestSortOrganizer {
// duplication
int currentSlot = startSlot;
for (ItemStack item : tempInventory.getContents()) {
// Ignore null ItemStacks. TODO: Actually, we could skip the for-loop here
// because
// our temporary inventory was already sorted. Feel free to make a pull request
// to
// save your server half a nanosecond :)
//if (item != null)
//{
while(unsortableSlots.contains(currentSlot) && currentSlot < endSlot) {
while (unsortableSlots.contains(currentSlot) && currentSlot < endSlot) {
currentSlot++;
}
inv.setItem(currentSlot, item);
//}
currentSlot++;
}
}
static int getNumberOfEnchantments(ItemStack is) {
int totalEnchants = 0;
//if(!is.getItemMeta().hasEnchants()) return 0;
if(is.getItemMeta() instanceof EnchantmentStorageMeta) {
EnchantmentStorageMeta storageMeta = (EnchantmentStorageMeta) is.getItemMeta();
Map<Enchantment,Integer> storedEnchants = storageMeta.getStoredEnchants();
for(int level : storedEnchants.values()) {
totalEnchants += level;
}
}
Map<Enchantment,Integer> enchants= is.getItemMeta().getEnchants();
for(int level : enchants.values()) {
totalEnchants += level;
}
return totalEnchants;
}
public void updateInventoryView(InventoryClickEvent event) {
for(HumanEntity viewer : event.getViewers()) {
if(viewer instanceof Player) {
for (HumanEntity viewer : event.getViewers()) {
if (viewer instanceof Player) {
Player playerViewer = (Player) viewer;
playerViewer.updateInventory();
}
@ -550,8 +528,8 @@ public class ChestSortOrganizer {
}
public void updateInventoryView(Inventory inventory) {
for(HumanEntity viewer : inventory.getViewers()) {
if(viewer instanceof Player) {
for (HumanEntity viewer : inventory.getViewers()) {
if (viewer instanceof Player) {
Player playerViewer = (Player) viewer;
playerViewer.updateInventory();
}
@ -562,36 +540,41 @@ public class ChestSortOrganizer {
return item != null && item.getAmount() > 64;
}
public void stuffInventoryIntoAnother(Inventory source, Inventory destination,Inventory origSource, boolean onlyMatchingStuff) {
/*public void stuffPlayerInventoryIntoAnother(PlayerInventory source, Inventory destination) {
stuffPlayerInventoryIntoAnother(source,destination,false);
}*/
public void stuffInventoryIntoAnother(Inventory source, Inventory destination, Inventory origSource, boolean onlyMatchingStuff) {
Material placeholderMaterial = Material.DIRT;
ItemStack[] hotbarStuff = new ItemStack[9];
boolean destinationIsPlayerInventory = true;
if(destination.getHolder()==null || !(destination.getHolder() instanceof Player) || destination.getType() != InventoryType.PLAYER) {
if (destination.getHolder() == null || !(destination.getHolder() instanceof Player) || destination.getType() != InventoryType.PLAYER) {
destinationIsPlayerInventory = false;
}
// Dont fill hotbar
if(destinationIsPlayerInventory) {
for(int i = 0; i<9;i++) {
if (destinationIsPlayerInventory) {
for (int i = 0; i < 9; i++) {
hotbarStuff[i] = destination.getItem(i);
destination.setItem(i, new ItemStack(placeholderMaterial,64));
destination.setItem(i, new ItemStack(placeholderMaterial, 64));
}
}
ArrayList<ItemStack> leftovers = new ArrayList<>();
for(int i = 0;i<source.getSize();i++) {
for (int i = 0; i < source.getSize(); i++) {
ItemStack current = source.getItem(i);
if(current == null) continue;
if(onlyMatchingStuff && !doesInventoryContain(destination,current.getType())) continue;
if(isOversizedStack(current)) continue;
if (current == null) continue;
if (onlyMatchingStuff && !doesInventoryContain(destination, current.getType())) continue;
if (isOversizedStack(current)) continue;
source.clear(i);
HashMap<Integer,ItemStack> currentLeftovers = destination.addItem(current);
HashMap<Integer, ItemStack> currentLeftovers = destination.addItem(current);
leftovers.addAll(currentLeftovers.values());
@ -600,8 +583,8 @@ public class ChestSortOrganizer {
origSource.addItem(leftovers.toArray(new ItemStack[0]));
// Restore hotbar
if(destinationIsPlayerInventory) {
for(int i=0;i<9;i++) {
if (destinationIsPlayerInventory) {
for (int i = 0; i < 9; i++) {
destination.setItem(i, hotbarStuff[i]);
}
}
@ -611,49 +594,33 @@ public class ChestSortOrganizer {
}
/*public void stuffPlayerInventoryIntoAnother(PlayerInventory source, Inventory destination) {
stuffPlayerInventoryIntoAnother(source,destination,false);
}*/
public void stuffPlayerInventoryIntoAnother(PlayerInventory source,
Inventory destination, boolean onlyMatchingStuff) {
boolean destinationIsShulkerBox = destination.getType().name().equalsIgnoreCase("SHULKER_BOX");
Inventory temp = Bukkit.createInventory(null, maxInventorySize);
for(int i = playerInvStartSlot;i<=playerInvEndSlot;i++) {
for (int i = playerInvStartSlot; i <= playerInvEndSlot; i++) {
ItemStack currentItem = source.getItem(i);
if(currentItem==null) continue;
if (currentItem == null) continue;
// This prevents Minepacks from being put into Minepacks
/*if(plugin.hookMinepacks && plugin.listener.minepacksHook.isMinepacksBackpack(destination)
&& plugin.listener.minepacksHook.isMinepacksBackpack(currentItem)) continue;*/
// This prevents Minepacks from being moved at all
if(plugin.hookMinepacks && plugin.listener.minepacksHook.isMinepacksBackpack(currentItem)) continue;
if (plugin.hookMinepacks && plugin.listener.minepacksHook.isMinepacksBackpack(currentItem)) continue;
if(plugin.hookInventoryPages
if (plugin.hookInventoryPages
&& plugin.organizer.inventoryPagesHook.isButton(currentItem, i, source)) continue;
if(destinationIsShulkerBox && currentItem.getType().name().endsWith("SHULKER_BOX")) continue;
if (destinationIsShulkerBox && currentItem.getType().name().endsWith("SHULKER_BOX")) continue;
if(isOversizedStack(currentItem)) continue;
if (isOversizedStack(currentItem)) continue;
if(onlyMatchingStuff && !doesInventoryContain(destination,currentItem.getType())) continue;
if (onlyMatchingStuff && !doesInventoryContain(destination, currentItem.getType())) continue;
temp.addItem(currentItem);
source.clear(i);
}
stuffInventoryIntoAnother(temp,destination,source,false);
}
static boolean doesInventoryContain(Inventory inv, Material mat) {
for(ItemStack item : inv.getContents()) {
if(item==null) continue;
if(item.getType() == mat) {
return true;
}
}
return false;
stuffInventoryIntoAnother(temp, destination, source, false);
}
}

View File

@ -10,6 +10,7 @@ import org.bukkit.inventory.PlayerInventory;
import de.jeff_media.ChestSort.ChestSortPlugin;
import net.md_5.bungee.api.ChatColor;
import org.jetbrains.annotations.NotNull;
public class InventoryPagesHook {
@ -48,7 +49,7 @@ public class InventoryPagesHook {
}
public boolean isButton(ItemStack item, int slot, Inventory inv) {
public boolean isButton(@NotNull ItemStack item, int slot, @NotNull Inventory inv) {
if(!plugin.hookInventoryPages) {
return false;
@ -58,10 +59,6 @@ public class InventoryPagesHook {
return false;
}
if(item == null) return false;
//System.out.println("Checking if slot " + slot + " "+ item.toString() + " is button");
// When using &f as color, we manually have to add this to the string because it gets removed by InventoryPages
if(prevName.startsWith("§f")) prevName = prevName.substring(2);
if(nextName.startsWith("§f")) nextName = nextName.substring(2);

View File

@ -13,6 +13,7 @@ public class MinepacksHook {
final ChestSortPlugin plugin;
MinepacksPlugin minepacks = null;
boolean skipReflection = false;
public MinepacksHook(ChestSortPlugin plugin) {
this.plugin = plugin;
@ -25,9 +26,11 @@ public class MinepacksHook {
public boolean isMinepacksBackpack(ItemStack item) {
if(minepacks == null) return false;
if(skipReflection && minepacks.isBackpackItem(item)) return true;
try {
minepacks.getClass().getMethod("isBackpackItem", ItemStack.class);
skipReflection=true;
if(minepacks.isBackpackItem(item)) return true;
} catch (NoSuchMethodException | SecurityException e) {
plugin.getLogger().warning("You are using a version of Minepacks that is too old and does not implement every API method needed by ChestSort. Minepacks hook will be disabled.");

View File

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