Solved problem resetting chest inventory

Discussion in 'Plugin Development' started by Jusi, Jan 11, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    Jusi

    For resetting the world later, I am loggingchest usage.

    First, removing added items from the chest works perfectly fine.
    The problem is that instead of filling up the chestwith the saved item stacks only single items are placed, stacks with changed size aren't touched at all.
    It seems like the item types are saved and set correctly but the stack size is completely untouched.

    So how do I save and setthe stack size correctly?

    The following code is saving the chest inventory:

    Code:
    //********************************PlayerInteraction**********************************************************
        
        public static HashMap<Location, ItemStack[]> NCChanged = new HashMap<Location, ItemStack[]>();   
    //stuff
     
    @EventHandler
        public void onPlayerInteract (PlayerInteractEvent event)
        {
            Player player = event.getPlayer();
            Block block = event.getClickedBlock();
            if (player == null || block == null)
            {return;}
            int BTId = block.getTypeId();
            String BlockType = block.getType().toString();
            if(NCChanged.containsKey(block.getLocation()) == false && BTId == 54)
            {
                Chest chest = (Chest) block.getState();
                ItemStack[] inventory = chest.getBlockInventory().getContents();  //gets the inventory
                NCChanged.put(block.getLocation(), inventory);   //saves the inventory
                getServer().broadcastMessage(ChatColor.YELLOW + inventory);           
            } 
    }      
    and these are the lines loading and settingit:
    Code:
    for(Location lnc : NCChanged.keySet())
                            {
                                plugin.getServer().broadcastMessage(ChatColor.YELLOW + " Chest reset.");
                                ItemStack[] ncinv =  NCChanged.get(lnc);   //loads the saved inventory
                                BlockState ncbs = lnc.getBlock().getState();
                                Chest nchest = (Chest) ncbs;  //gets the chest
                                nchest.getBlockInventory().setContents(ncinv);   //sets the inventory
                                nchest.update();
                            }
     
  2. Offline

    Sheepii

    You know you don't need to return on a void right? try deleting the null checker and add this:
    if (!player == null && !block == null){

    Also, why not use .getType() == Material.CHEST?

    Are you sure that .getContents() returns ItemStack[]
     
  3. Offline

    Jusi

    Sheepii
    I am sorry but I don't want to argue about style and these things...
    What you're suggesting does exactly the same thingsas it's doing right now.
    If you check at http://jd.bukkit.org/apidocs/ you'll find out that ItemStack[] is exactly what .getContents() returns. :D
     
  4. Offline

    Sheepii

    Jusi
    I wasn't arguing, I didn't legitimately know if getContents() returns ItemStack[].
    You don't need to be so defensive, especially to someone who is trying to help you, with that kind of additude no one would want to help you. First off, you need to see if the hashmap contains your chest. Because if it does, you're just putting location, Itemstack[] over and over again onto the hashmap. So you need to remove it, then update it, but placing it again.

    try saving the inventory b:
    public static HashMap<Location, Inventory> NCChanged = new HashMap<Location, Inventory>();
    Location loc = block.getLocation();
    if(NCChanged.contains(loc)){
    NCChanged.remove(loc, null);
    if(InventoryType.CHEST){
    NCChanged. put(block.getLocation(), block.getInventory())

    Then whenever you want to get the inventory, just
    Location loc = block.getLocation();
    Inventory inv = (Inventory) NCC.getInventory(loc);

    inv.whateveryouwantittodo();


    Or, alternatively, you could look into InventoryEvent.
     
  5. Offline

    Jusi

    Hmmm good idea, using inventory instead of itemstack[]. I'll check how well it works tomorrow.
    I'm sorry if I sounded a bit harsh, it was not intended and might just be caused by the fact that I'm not native English speaking.;)
     
  6. Offline

    Sheepii

    With my code you want to check if the inventorytype is a chest first. I got it mixed up with if(NCChanged.contains(loc)){ So check if the inventory is a chest, then check if NCChanged contains loc, then remove it from NCChanged.

    Also, when setting the inventory, you want to change this:
    nchest.getBlockInventory().setContents(ncinv);
    With this:
    nchest.getBlockInventory().setContents(inv.getContents());
     
  7. Offline

    Jusi

    Well, I've finally figured it out completely. For those who migh need it, here's the solution and the final code. Ichecked out multiple possible solutions like four-dimensional arrays, HashSetsand all that fancy stuff.:rolleyes:
    I've come to these conclusions:
    - with saving the inventory itself you only can savethe "container" itself, not what's in it.
    - The ItemStack[] way at least worked for theitem type so I solved the problem by saving the stack's sizein a separate HashMap.

    The HashMap definitions:
    Code:
    public static HashMap<Location, ItemStack[]> NCChanged = new HashMap<Location, ItemStack[]>();
        public static HashMap<Location, byte[]> NCAmount = new HashMap<Location, byte[]>();

    The saving lines:
    //******************************************************chest logger**********************************************************************************
    if(NCChanged.containsKey(location) == false && NDCList.contains(location) == false && BTId == 54)
    {
    int X = (int)location.getX();
    int Y = (int)location.getY();
    int Z = (int)location.getZ();
    World world = location.getWorld();
    Location[] lSide = new Location[4];
    lSide[0] = new Location(world, X, Y, Z + 1);
    lSide[1] = new Location(world, X, Y, Z - 1);
    lSide[2] = new Location(world, X + 1, Y, Z);
    lSide[3] = new Location(world, X - 1, Y, Z);
    if(lSide[0].getBlock().getTypeId() == 54 || lSide[1].getBlock().getTypeId() == 54 || lSide[2].getBlock().getTypeId() == 54 || lSide[3].getBlock().getTypeId() == 54)
    {
    for (byte Li = 0; Li<4; Li++)
    {
    if(lSide[Li].getBlock().getTypeId() == 54)
    {
    NDCList.add(lSide[Li]);
    }
    }
    Chest chest = (Chest) block.getState();
    byte[] NCAPos = new byte[54];
    ItemStack[] inv = chest.getInventory().getContents();
    NCChanged.put(location, inv);
    for (byte q = 0; q<54; q++)
    {
    if (chest.getInventory().getItem(q) != null)
    {
    NCAPos[q] = (byte)chest.getInventory().getItem(q).getAmount();
    }
    }
    NCAmount.put(location, NCAPos);
    }
    else
    {
    Chest chest = (Chest) block.getState();
    byte[] NCAPos = new byte[27];
    ItemStack[] inv = chest.getInventory().getContents();
    NCChanged.put(location, inv);
    for (byte q = 0; q<27; q++)
    {
    if (chest.getInventory().getItem(q) != null)
    {
    NCAPos[q] = (byte)chest.getInventory().getItem(q).getAmount();
    }
    }
    NCAmount.put(location, NCAPos);
    }
    }
    To avoid NPEs you always should check if the item stack is empty. As well - as Sheepii mentioned - don't delete the contains part since it prevents the saved data from being overwritten.
    Note that I added some lines to also save double chests properly!



    The loading lines:
    Code:
    for (Location loc : NCChanged.keySet())
                            {
                                byte[] NCAPos = NCAmount.get(loc);
                                BlockState bs = loc.getBlock().getState();
                                Chest chest = (Chest) bs;
                                chest.getInventory().setContents(NCChanged.get(loc));
                                byte b = (byte)NCAPos.length;
                                for (byte q = 0; q < b; q++)
                                {                                
                                    ItemStack is = chest.getInventory().getItem(q);
                                    if (is != null)
                                    {
                                    int item = is.getTypeId();
                                    ItemStack iReplace = new ItemStack(item, NCAPos[q]);
                                    chest.getInventory().setItem(q, iReplace);
                                    }
                                }
                            }
    
    Remember to check if the block still is a chest and reset it or cancel resetting the inventory, I didn't include that stuff in this extract.
     
Thread Status:
Not open for further replies.

Share This Page