Solved Help with Sort Inventory Plugin

Discussion in 'Spigot Plugin Development' started by GeorgeZ, Jun 1, 2016.

  1. Hello! I am having trouble right now with my inventory sort plugin. Right now, I have everything that I want working properly, the items from index 9 to 35 are being sorted in alphabetical order. However, I am using ItemStacks, which means after everything is sorted there can still be slots of ItemStacks that don't combine with each other. I would like to, somewhere in the sorting process, combine stacks of similar items.

    Here is my CommandSort class:
    Code (Text):
    package com.george.invPlugin;

    import java.util.ArrayList;

    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.PlayerInventory;

    public class CommandSort implements CommandExecutor {
       
        ArrayList<ItemStack> itemlist = new ArrayList<ItemStack>();
       
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (sender instanceof Player) {
                Player player = (Player) sender;
                PlayerInventory inv = player.getInventory();
                for (int i = 9; i < 36 ; i ++) {
                    ItemStack item = inv.getItem(i);
                    if (item == null) {
                        item = new ItemStack(Material.AIR);
                    }
                    itemlist.add(item);    
                    inv.clear(i);              
                }
                ArrayList<ItemStack> sortedlist = SortMain.SortArrayList(itemlist);
                int it = 9;
                for (ItemStack item : sortedlist) {
                    inv.setItem(it, item);
                    it ++;
                }
                itemlist.clear();
                sortedlist.clear();
            }
            return true;
        }
    }
     
    Here is my SortMain class (I realize that itemValue and itemDurability etc aren't being used, I just have them there for future/potential sorting methods):
    Code (Text):
    package com.george.invPlugin;

    import java.util.ArrayList;

    import org.bukkit.Material;
    import org.bukkit.inventory.ItemStack;

    public final class SortMain {

        public void setItemlist(ArrayList<ItemStack> itemlist) {
            this.itemlist = itemlist;
        }

        @SuppressWarnings("unused")
        private ArrayList<ItemStack> itemlist;

        @SuppressWarnings("unused")
        private static Material itemValue(ItemStack item) {
            return item.getType();
        }

        private static String itemName(ItemStack item) {
            return item.getType().name();
        }

        @SuppressWarnings("unused")
        private static short itemDurability(ItemStack item) {
            return item.getDurability();
        }
       
        @SuppressWarnings("unused")
        private static int itemAmount(ItemStack item) {
            return item.getAmount();
        }
           
        public static ArrayList<ItemStack> SortArrayList(ArrayList<ItemStack> itemlist) {
            //System.out.println("UNSORTED: " + itemlist);
            ArrayList<ItemStack> sortedItemlist = BubbleSort(itemlist);
            //System.out.println("SORTED: " + sortedItemlist);
            return sortedItemlist;
        }
       
        private static ArrayList<ItemStack> BubbleSort (ArrayList<ItemStack> itemlist) {
            ArrayList<ItemStack> sortedItemlist = itemlist;
            for (int i = 0; i < sortedItemlist.size() - 1; i++) {          
                for (int j = 1; j < sortedItemlist.size() - i; j++) {              
                    if (compare(sortedItemlist.get(j-1), sortedItemlist.get(j)) < 0) {
                        ItemStack temp = itemlist.get(j-1);
                        sortedItemlist.set(j-1, sortedItemlist.get(j));
                        sortedItemlist.set(j, temp);                  
                    }
                }
            }
            return sortedItemlist;
        }
       
        private static int compare(ItemStack o1, ItemStack o2) {
            return (itemName(o1)).compareTo(itemName(o2));
        }  
    }
     
    Thank you so much for your time and help!
     
  2. I've had a similar issue and solved it using a wrapper for ItemStack and a map. Here is a link to the thread. However it might screw up your sorting. Maybe it would work for you if you'd combine them before you sort them?
     
    • Useful Useful x 1
  3. So before sending off my array list to be sorted I would make put the array list through the wrapper/map?

    Edit: Thanks for the quick reply by the way
     
  4. Yes...here is the class I wrote, if you want to test it.
     
    • Useful Useful x 1
  5. Thanks! I played around with it and it seems to work well. Right now I noticed two things though, the first is that I had two stacks of cobblestone totaling 72, and when combined it turns into a stack of 72 rather than a stack of 64 and a stack of 8. The second is that Lapis Lazuli and dyes are turned into an ink sac, which I believe is something to do with how I'm saving out the ItemStack information which I am going to try to play with now. How would you go about the stack size being above max stack size?

    Thanks again! I feel like my plugin is getting so close for me to use personally lol
     
  6. Consider using a Comparator with Collections.sort(List<>, Comparator)
     
  7. For the item amounts?
     
    • Useful Useful x 1
  8. Ah ha! I figured it out! I took the example of the worldgaurd stuff and used that to stack all items together before I did anything else! (I was having trouble if it was anywhere other than before I started saving info)

    Code (Text):
    package com.george.invPlugin;

    import java.util.ArrayList;

    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.PlayerInventory;

    public class CommandSort implements CommandExecutor {
       
        ArrayList<ItemStack> itemlist = new ArrayList<ItemStack>();
       
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (sender instanceof Player) {
                // Setting player and inventory variables
                Player player = (Player) sender;
                PlayerInventory inv = player.getInventory();
               
                ItemStack[] items = inv.getContents();
                int len = inv.getSize();
                int affected = 0;
                for (int i = 0; i < len; i++) {
                    ItemStack item = items[i];
                    // Avoid infinite stacks and stacks with durability
                    if (item == null || item.getAmount() <= 0) {
                        continue;
                    }
                    int max = item.getMaxStackSize();
                    if (item.getAmount() < max) {
                        int needed = max - item.getAmount();
                        // Find another stack of the same type
                        for (int j = i + 1; j < inv.getSize(); j++) {
                            ItemStack item2 = items[j];
                            // Avoid infinite stacks and stacks with durability
                            if (item2 == null || item2.getAmount() <= 0
                                    || (item.getMaxStackSize() == 1)) {
                                continue;
                            }
                            if (item2.getType() == item.getType()) {
                                // This stack won't fit in the parent stack
                                if (item2.getAmount() > needed) {
                                    item.setAmount(max);
                                    item2.setAmount(item2.getAmount() - needed);
                                    break;
                                }
                                // This stack will
                                else {
                                    items[j] = null;
                                    item.setAmount(item.getAmount() + item2.getAmount());
                                    needed = max - item.getAmount();
                                }
                                affected ++;
                            }
                        }
                    }
                    if (affected > 0) {
                        player.getInventory().setContents(items);
                    }
                }
                // Loop through inventory and add to itemlist
                for (int i = 9; i < 36 ; i ++) {
                    ItemStack item = inv.getItem(i);
                    // Make sure if slot is empty that it will add air instead
                    if (item == null) {
                        item = new ItemStack(Material.AIR);
                    }
                    // Add ItemStack to itemlist
                    itemlist.add(item);
                    inv.clear(i);
                }
                // Send itemlist to CombineMain to combine ItmeStacks
                //ArrayList<ItemStack> combinedlist = CombineMain.CombineArrayList(itemlist);
                // Send combinedlist to SortMain Class to be sorted and set sortedlist
                ArrayList<ItemStack> sortedlist = SortMain.SortArrayList(itemlist);
                // 9 is the first slot not in the hotbar
                int it = 9;
                // Add items of sortedlist to the players inventory
                for (ItemStack item : sortedlist) {
                    inv.setItem(it, item);
                    // Because setItem() takes an index and an item as arguments, add one to the index so the next item doesn't overwrite the previous
                    it ++;
                }
                // Reset lists and integers
                it = 9;
                itemlist.clear();
                //combinedlist.clear();
                sortedlist.clear();
            }
            return true;
        }
    }
     
    Next step is to try to save out ink and dye information, as well as durability!

    Thanks for your help everyone!
     
  9. Durability is easy, ItemStack has getter and setter methods for that. Not sure about dye information though. Methods regarding the IDs are deprecated, not sure how to handle it now. But I'd also like to know^^